When I try those code below:
function f(x)
Meta.parse("x -> x " * x) |> eval
end
function g(x)
findall(Base.invokelatest(f,x),[1,2,3]) |> println
end
g("<3")
Julia throws "The applicable method may be too new" error.
If I tried these code below:
function f(x)
Meta.parse("x -> x " * x) |> eval
end
findall(f("<3"),[1,2,3]) |> println
Julia could give me corrected result: [1, 2]
How can I modify the first codes to use an String to generate function in other function, Thx!
Test in Julia 1.6.7
Do
function g(x)
h = f(x)
findall(x -> Base.invokelatest(h, x) ,[1,2,3]) |> println
end
g("<3")
The difference in your code is that when you write:
Base.invokelatest(f, x)
you invoke f, but f is not redefined. What you want to do is invokelatest the function that is returned by f instead.
Use a macro instead of function:
macro f(expr)
Meta.parse("x -> x " * expr)
end
Now you can just do:
julia> filter(#f("<3"), [1,2,3])
2-element Vector{Int64}:
1
2
Related
As a minimal example of what I want to do:
(defn mkfn [func]
(fn func [a] (print "I am a function")))
(mkfn 'x) ; => #function[user/mkfn/func--10871]
(type x)
(x)
The last two both result in:
Syntax error compiling at (conjure-log-12628.cljc:1:1).
Unable to resolve symbol: x in this context
I'm not sure why this doesn't work since fn takes symbols as input and 'x is a symbol. I'm also not sure how to accomplish this task.
For that matter:
user=> (def (eval 'y) 3)
Syntax error compiling def at (conjure-log-12628.cljc:1:1).
user=> (def 'y 3)
Syntax error compiling def at (conjure-log-12628.cljc:1:1).
First argument to def must be a Symbol
First argument to def must be a Symbol
user=> (type 'y)
clojure.lang.Symbol
Other things that don't work:
(defn mkfn [func]
(fn (sympol func) [a] (print "i am a function")))
(symbol "y") ; => y ; a symbol
(def (symbol "y") 3) ; => an err
You will probably need a macro. It seems that you want to call that function by the provided name, so you also have to replace fn with defn.
And you have to be careful about a number of arguments, because function x with argument vector [a] must be called with one argument, and not like (x).
(defmacro mkfn [func]
`(defn ~func [~'a]
(print "I am a function")))
(mkfn x)
=> #'user/x
(x 1)
I am a function=> nil
There is also other way, using intern, so you can completely avoid writing macros:
(intern *ns* 'x (fn [a] (print "I am a function")))
=> #object...
(x 1)
I am a function=> nil
Example with intern:
(defn mkfn [func]
(intern *ns* func (fn [a] (print "I am a function"))))
=> #'user/mkfn
(mkfn 'y)
=> #'user/y
(y 1)
I am a function=> nil
As for your errors, def is a special form, so it has different evaluation rules. It doesn't evaluate the first argument, which has to be a symbol- and (unevaluated) (eval 'y), 'y or (symbol "y") aren't symbols, while y is.
You gonna need a macro for that since you need code writing code.
(defmacro mkfn [func]
`(fn ~func [~'a] ...))
There 2 ways of doing it, either function plus eval or macro. If you really want to programatically create a new function with your chosen name, the macro solution is the way to go.
The function + eval solution is instructive, but you'll have to either quote the function name when you call it (via a 2nd eval) or save the created function in another variable when you create it.
If you are interested in writing macros, please see this other question first: How do I write a Clojure threading macro?
For the function + eval, we can start with my favorite template project and add the following:
(ns tst.demo.core
(:use demo.core tupelo.core tupelo.test))
(defn maker-eval
[fn-sym]
(let [ll (list 'fn 'anon-fn [] (str "I am " fn-sym))]
(spyx :eval ll)
(eval ll)))
(verify
(let [anon-fn-1 (maker-eval 'aaa)]
(is= "I am aaa" (anon-fn-1))) ; need the temp local variable
(let [anon-fn-2 (maker-eval 'bbb)]
(is= "I am bbb" (anon-fn-2))) ; need the temp local variable
)
and we can see the creation and use of the function, along with printed output:
:eval ll => (fn anon-fn [] "I am aaa")
:eval ll => (fn anon-fn [] "I am bbb")
For the macro version, we type
(defn maker-macro-impl
[fn-sym]
(let [ll `(defn ~fn-sym [] (str "I am " (str (quote ~fn-sym))))]
(spyx :macro ll)
ll))
(defmacro maker-macro
[fn-sym] (maker-macro-impl fn-sym))
(verify
(let [anon-fn-3 (maker-macro-impl 'ccc)]
(is= anon-fn-3 (quote
(clojure.core/defn ccc [] (clojure.core/str "I am " (clojure.core/str (quote ccc)))))))
(maker-macro ddd)
(is= (ddd) "I am ddd"))
and see printed:
:macro ll => (clojure.core/defn ccc [] (clojure.core/str "I am " (clojure.core/str (quote ccc))))
Note that the local variable anon-fn-3 was only used to test the maker-macro-impl function, but was not needed to call the newly-created function ddd
at the end of the unit test.
I'm trying to write a function that calls a function with a specified name and arity:
my_fun(FunctionName, Arity) ->
%Call FunctionName/Arity
.
So that calling it like this:
my_fun(foo, 3)
should result in a call to function foo/3.
The problem is, I don't know how to call a function if only its name and arity are specified. The function I'm trying to call is guaranteed to exist in the same module from which I'm trying to call it.
Is it possible to implement this in Erlang, and how?
You can use erlang:apply/3 with the first argument being ?MODULE to refer to the same module, the second one being the name of the function as an atom and the third one being a list containing Arity elements:
-module(a).
-compile(export_all).
my_fun(FunctionName, Arity) ->
apply(?MODULE, FunctionName, lists:seq(1, Arity)).
foo(A, B, C) ->
io:format("~p ~p ~p~n", [A, B, C]).
bar(A, B) ->
io:format("~p ~p~n", [A, B]).
main() ->
my_fun(foo, 3),
my_fun(bar, 2).
Output:
1> c(a), a:main().
1 2 3
1 2
Not really clear what you want to do...
Does this help you?
-module (cf).
-export ([cf/2,test/0,f/1,f/2,f/3]).
cf(F,1) ->
fun(P1) -> apply(cf,F,[P1]) end;
cf(F,2) ->
fun(P1,P2) -> apply(cf,F,[P1,P2]) end;
cf(F,3) ->
fun(P1,P2,P3) -> apply(cf,F,[P1,P2,P3]) end.
f(X) -> lists:seq(1,X).
f(X,Y) -> X+Y.
f(X,Y,Z) -> {X,Y,Z}.
test() ->
A = cf(f,1),
B = cf(f,2),
C = cf(f,3),
{A(3),B(5,6),C(a,12,"hello")}.
1> c(cf).
{ok,cf}
2> cf:test().
{[1,2,3],11,{a,12,"hello"}}
But this is just hiding the function: apply(Module,Function,Args), I don't see the advantage to do not use it directly.
In my simple Haskell DSL, I have the following functions to call other functions:
callF :: forall a. (Typeable a)
=> (V a) -> (V a)
callF fp#(V (FunP name)) =
pack $ FunAppl (prettyV fp) []
callF1 :: forall a b. (Typeable a, Typeable b)
=> (V (V a -> V b)) -> V a -> (V b)
callF1 fp#(V (FunP name)) arg =
pack $ FunAppl (prettyV fp) [prettyV arg]
callF2 :: forall a b c. (Typeable a, Typeable b, Typeable c)
=> (V (V a -> V b -> V c)) -> V a -> V b -> (V c)
callF2 fp#(V (FunP name)) arg1 arg2 =
pack $ FunAppl (prettyV fp) [prettyV arg1, prettyV arg2]
I would like to generalize this for any number of arguments using typeclasses.
This is what I've tried, but it only works for 0 or 1 arguments, and it doesn't enforce calling functions with the correct number of arguments.
class Callable a b | a -> b where
call :: V a -> [String] -> b
instance Callable a (V b) where
call fp#(V (FunP name)) x = pack $ FunAppl (prettyV fp) x
instance (Typeable c, Typeable d) => Callable (V a -> V b) (V c -> V d) where
call fun#(V (FunP name)) list arg = call fun (list ++ [prettyV arg])
The normal technique for functions with multiple arguments--like printf--is to use a recursive typeclass. For printf, this is done with a class called PrintfType. The important insight is the recursive instance:
(PrintfArg a, PrintfType r) => PrintfType (a -> r)
This basically says that if you can return a PrintfType, your function is also an instance. The "base case" is then a type like String. So, if you want to call printf with one argument, it fires two instances: PrintfType String and PrintfType (a -> r) where r is String. If you want two arguments, it goes: String, (a -> r) where r is String and (a -> r) where r is the previous (a -> r).
However, your problem is actually a bit more complex. You want to have an instance that handles two different tasks. You want your instance to apply to functions of different types (e.g. V (V a -> V b), V (V a -> V b -> V c) and so on) as well as ensuring that the right number of arguments is presented.
The first step to do this is to stop using [String] to pass in arguments. The [String] type loses information about how many values it has, so you can't check that there is an appropriate number of arguments. Instead, you should use a type for the argument lists that reflects how many arguments it has.
This type could look something like this:
data a :. b = a :. b
it is just a type for combining two other types, which can be used like this:
"foo" :. "bar" :: String :. String
"foo" :. "bar" :. "baz" :: String :. String :. String
Now you just need to write a typeclass with a recursive instance that traverses both the type-level list of arguments and the function itself. Here's a very rough standalone sketch of what I mean; you'll have to adopt it to your particular problem yourself.
infixr 8 :.
data a :. b = a :. b
class Callable f a b | f -> a b where
call :: V f -> a -> b
instance Callable rf ra (V rb) => Callable (String -> rf) (String :. ra) (V rb) where
call (V f) (a :. rest) = call (V (f a)) rest
instance Callable String () (V String) where
call (V f) () = V f
You will also have to enable a few extensions: FlexibleInstances, FucntionalDepenedencies and UndecidableInstances.
You could then use it like this:
*Main> call (V "foo") ()
V "foo"
*Main> call (V (\ x -> "foo " ++ x)) ("bar" :. ())
V "foo bar"
*Main> call (V (\ x y -> "foo " ++ x ++ y)) ("bar" :. " baz" :. ())
V "foo bar baz"
If you pass in the wrong number of arguments, you will get a type error. Admittedly, it's not the prettiest error message in the world! That said, the important part of the error (Couldn't match type `()' with `[Char] :. ()') does point out the core problem (argument lists that don't match), which should be easy enough to follow.
*Main> call (V (\ x -> "foo " ++ x)) ("bar" :. "baz" :. ())
<interactive>:101:1:
Couldn't match type `()' with `[Char] :. ()'
When using functional dependencies to combine
Callable String () (V String),
arising from the dependency `f -> a b'
in the instance declaration at /home/tikhon/Documents/so/call.hs:16:14
Callable [Char] ([Char] :. ()) (V [Char]),
arising from a use of `call' at <interactive>:101:1-4
In the expression:
call (V (\ x -> "foo " ++ x)) ("bar" :. "baz" :. ())
In an equation for `it':
it = call (V (\ x -> "foo " ++ x)) ("bar" :. "baz" :. ())
Note that this might be a bit over-complicated for your particular task--I'm not convinced it's the best solution to the problem. But it's a very good exercise in enforcing more complicated type-level invariants using some more advanced typeclass features.
I have a function in a module that looks something like this:
module MyLibrary (throwIfNegative) where
throwIfNegative :: Integral i => i -> String
throwIfNegative n | n < 0 = error "negative"
| otherwise = "no worries"
I could of course return Maybe String or some other variant, but I think it's fair to say that it's a programmer error to call this function with a negative number so using error is justified here.
Now, since I like having my test coverage at 100% I want to have a test case that checks this behavior. I have tried this
import Control.Exception
import Test.HUnit
import MyLibrary
case_negative =
handleJust errorCalls (const $ return ()) $ do
evaluate $ throwIfNegative (-1)
assertFailure "must throw when given a negative number"
where errorCalls (ErrorCall _) = Just ()
main = runTestTT $ TestCase case_negative
and it sort of works, but it fails when compiling with optimizations:
$ ghc --make -O Test.hs
$ ./Test
### Failure:
must throw when given a negative number
Cases: 1 Tried: 1 Errors: 0 Failures: 1
I'm not sure what's happening here. It seems like despite my use of evaluate, the function does not get evaluated. Also, it works again if I do any of these steps:
Remove HUnit and call the code directly
Move throwIfNegative to the same module as the test case
Remove the type signature of throwIfNegative
I assume this is because it causes the optimizations to be applied differently. Any pointers?
Optimizations, strictness, and imprecise exceptions can be a bit tricky.
The easiest way to reproduce this problem above is with a NOINLINE on throwIfNegative (the function isn't being inlined across module boundaries either):
import Control.Exception
import Test.HUnit
throwIfNegative :: Int -> String
throwIfNegative n | n < 0 = error "negative"
| otherwise = "no worries"
{-# NOINLINE throwIfNegative #-}
case_negative =
handleJust errorCalls (const $ return ()) $ do
evaluate $ throwIfNegative (-1)
assertFailure "must throw when given a negative number"
where errorCalls (ErrorCall _) = Just ()
main = runTestTT $ TestCase case_negative
Reading the core, with optimizations on, the GHC inlines evaluate properly (?):
catch#
# ()
# SomeException
(\ _ ->
case throwIfNegative (I# (-1)) of _ -> ...
and then floats out the call to throwIfError, outside of the case scrutinizer:
lvl_sJb :: String
lvl_sJb = throwIfNegative lvl_sJc
lvl_sJc = I# (-1)
throwIfNegative =
\ (n_adO :: Int) ->
case n_adO of _ { I# x_aBb ->
case <# x_aBb 0 of _ {
False -> lvl_sCw; True -> error lvl_sCy
and strangely, at this point, no other code now calls lvl_sJb, so the entire test becomes dead code, and is stripped out -- GHC has determined that it is unused!
Using seq instead of evaluate is happy enough:
case_negative =
handleJust errorCalls (const $ return ()) $ do
throwIfNegative (-1) `seq` assertFailure "must throw when given a negative number"
where errorCalls (ErrorCall _) = Just ()
or a bang pattern:
case_negative =
handleJust errorCalls (const $ return ()) $ do
let !x = throwIfNegative (-1)
assertFailure "must throw when given a negative number"
where errorCalls (ErrorCall _) = Just ()
so I think we should look at the semantics of evaluate:
-- | Forces its argument to be evaluated to weak head normal form when
-- the resultant 'IO' action is executed. It can be used to order
-- evaluation with respect to other 'IO' operations; its semantics are
-- given by
--
-- > evaluate x `seq` y ==> y
-- > evaluate x `catch` f ==> (return $! x) `catch` f
-- > evaluate x >>= f ==> (return $! x) >>= f
--
-- /Note:/ the first equation implies that #(evaluate x)# is /not/ the
-- same as #(return $! x)#. A correct definition is
--
-- > evaluate x = (return $! x) >>= return
--
evaluate :: a -> IO a
evaluate a = IO $ \s -> let !va = a in (# s, va #) -- NB. see #2273
That #2273 bug is a pretty interesting read.
I think GHC is doing something suspicious here, and recommend not using evalaute (instead, use seq directly). This needs more thinking about what GHC is doing with the strictness.
I've filed a bug report to help get a determination from GHC HQ.
Given a higher-order function like the following:
let call (f : unit -> 'a) = f()
And another function:
let incr i = i + 1
Is there a way to pass incr to call, without using a lambda: (fun () -> incr 1)?
Obviously, passing (incr 1) does not work, as the function is then "fully applied."
EDIT
To clarify: I'm wondering if there's a way to curry a function, such that it becomes a function: unit -> 'a.
You can define such a shortcut yourself:
let ap f x = fun () -> f x
call (ap incr 1)
If the function you want to transform happens to be a pure function, you can define the constant function instead:
let ct x _ = x (* const is reserved for future use :( *)
call (ct (incr 1))
It looks more like an attempt to add laziness to strict F# then some kind of currying.
And in fact there is a built in facility for that in F#: http://msdn.microsoft.com/en-us/library/dd233247.aspx - lazy keyword plus awkward Force:
Not sure if it's any better than explicit lambda, but still:
let incr i =
printf "incr is called with %i\n" i
i+1
let call (f : unit -> 'a) =
printf "call is called\n"
f()
let r = call <| (lazy incr 5).Force
printf "%A\n" r