I have read that with a statically typed language like Scala or Haskell there is no way to create or provide a Lisp apply
function:
(apply #'+ (list 1 2 3)) => 6
or maybe
(apply #'list '(list :foo 1 2 "bar")) => (:FOO 1 2 "bar")
(apply #'nth (list 1 '(1 2 3))) => 2
Is this a truth?
A full APPLY is difficult in a static language.
In Lisp APPLY applies a function to a list of arguments. Both the function and the list of arguments are arguments to APPLY.
APPLY can use any function. That means that this could be any result type and any argument types.
APPLY takes arbitrary arguments in arbitrary length (in Common Lisp the length is restricted by an implementation specific constant value) with arbitrary and possibly different types.
APPLY returns any type of value that is returned by the function it got as an argument.
How would one type check that without subverting a static type system?
Examples:
Interaction example:
Now an example with the function REMOVE. We are going to remove the character a from a list of different things.
Note that you also can apply apply itself, since apply is a function.
There is also a slight complication because the function APPLY takes an arbitrary number of arguments, where only the last argument needs to be a list:
How to deal with that?
relax static type checking rules
restrict APPLY
One or both of above will have to be done in a typical statically type checked programming language. Neither will give you a fully statically checked and fully flexible APPLY.
A list in Haskell can only store values of one type, so you couldn't do funny stuff like
(apply substring ["Foo",2,3])
. Neither does Haskell have variadic functions, so(+)
can only ever take two arguments.There is a $ function in Haskell:
But that's only really useful because it has very low precedence, or as passing around HOFs.
I imagine you might be able to do something like this using tuple types and fundeps though?
I guess that's a sort of 'uncurryN', isn't it?
Edit: this doesn't actually compile; superseded by @FUZxxl's answer.
On this page, I read that "Apply is just like funcall, except that its final argument should be a list; the elements of that list are treated as if they were additional arguments to a funcall."
In Scala, functions can have varargs (variadic arguments), like the newer versions of Java. You can convert a list (or any Iterable object) into more vararg parameters using the notation
:_*
Example:In fact, even Java can do this. Java varargs can be passed either as a sequence of arguments or as an array. All you'd have to do is convert your Java
List
to an array to do the same thing.The benefit of a static language is that it would prevent you to apply a function to the arguments of incorrect types, so I think it's natural that it would be harder to do.
Given a list of arguments and a function, in Scala, a tuple would best capture the data since it can store values of different types. With that in mind
tupled
has some resemblance toapply
:For function of one argument, there is actually
apply
:I think if you think as apply as the mechanism to apply a first class function to its arguments, then the concept is there in Scala. But I suspect that
apply
in lisp is more powerful.See his dynamic thing for haskell, in C, void function pointers can be casted to other types, but you'd have to specify the type to cast it to. (I think, haven't done function pointers in a while)
It's trivial in Scala:
OK, typeless:
Perhaps I mixed up
funcall
andapply
, so: