• Understanding apply in MAL (clojure dialect)

    From none) (albert@21:1/5 to All on Thu Sep 21 09:36:56 2023
    Implementing mal according to https://github.com/kanaka/mal
    I have problems with the implementation of apply.

    (apply symbol? (list two) )
    should give true, but this test fails.

    This is the description with MAL.

    apply: takes at least two arguments. The first argument is a function
    and the last argument is a list (or vector). The arguments
    between the function and the last argument (if there are any) are
    concatenated with the final argument to create the arguments that
    are used to call the function. The apply function allows a
    function to be called with arguments that are contained in a list
    (or vector). In other words, (apply F A B [C D]) is equivalent to
    (F A B C D).

    There is no mention that it is a special function. So all the arguments
    of apply are evaluated.

    I imagine myself as a naive user.
    A naive user would apply to a list with the non-interned symbol two.

    (apply symbol? (two) )

    This doesn't work. (two) is not a list, but a call.
    We must do.
    (apply symbol? (list two) )
    But again list is not a special function. It evaluates its arguments.
    In order to have a list that contains the symbol `` two ''
    we must do:
    (apply symbol? (list (quote two))
    We arrive at the list to be evaluated
    (<#4623388> <two>) where #4623388 is the actual function symbol? refers to.

    This is an abstract structure tree: a list consisting of a a function
    and a symbol.

    Now we are supposed to evaluate this list.
    symbol? is not a special function. So we evaluate its arguments :
    `` two ''.
    Bang! ERROR 8010.
    8010 : Symbol not in environment

    My test succeeds if we
    (def! two 2)
    2

    (apply number? (list two) )
    true

    I cannot reasonably interpret the specification such that the
    given test succeeds.

    (apply symbol? (list (quote(quote two)))
    gives true if I test it.


    Groetjes Albert
    --
    Don't praise the day before the evening. One swallow doesn't make spring.
    You must not say "hey" before you have crossed the bridge. Don't sell the
    hide of the bear until you shot it. Better one bird in the hand than ten in
    the air. First gain is a cat spinning. - the Wise from Antrim -

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Spiros Bousbouras@21:1/5 to albert@cherry. on Thu Sep 21 11:10:36 2023
    On Thu, 21 Sep 2023 09:36:56 +0200
    albert@cherry.(none) (albert) wrote:
    Implementing mal according to https://github.com/kanaka/mal
    I have problems with the implementation of apply.

    (apply symbol? (list two) )
    should give true, but this test fails.

    This is the description with MAL.

    apply: takes at least two arguments. The first argument is a function
    and the last argument is a list (or vector). The arguments
    between the function and the last argument (if there are any) are
    concatenated with the final argument to create the arguments that
    are used to call the function. The apply function allows a
    function to be called with arguments that are contained in a list
    (or vector). In other words, (apply F A B [C D]) is equivalent to
    (F A B C D).

    Either the specification is inaccurate or MAL does things differently than Common Lisp ; it is probably the former. Probably what it means is that

    (apply F A B [C D]) is equivalent to doing the call
    (F <value of A> <value of B> <value of C> <value of D>)

    There is no mention that it is a special function. So all the arguments
    of apply are evaluated.

    Correct.

    I imagine myself as a naive user.
    A naive user would apply to a list with the non-interned symbol two.

    (apply symbol? (two) )

    This doesn't work. (two) is not a list, but a call.

    True. Also I assume there is no variable named symbol? although there is
    a function named symbol? .It could be of course that in MAL there is no
    such distinction.So you do
    (apply symbol? (quote (two)))
    or
    (apply (quote symbol?) (quote (two)))

    depending on whether MAL is a Lisp 1 or Lisp 2.

    We must do.
    (apply symbol? (list two) )
    But again list is not a special function. It evaluates its arguments.
    In order to have a list that contains the symbol `` two ''
    we must do:
    (apply symbol? (list (quote two))

    Your parentheses don't match. But you probably mean
    (apply symbol? (list (quote two)))

    We arrive at the list to be evaluated
    (<#4623388> <two>) where #4623388 is the actual function symbol? refers to.

    This is an abstract structure tree: a list consisting of a a function
    and a symbol.

    Now we are supposed to evaluate this list.

    No ; you are supposed to call function symbol? with 1 argument which is the symbol two .In other words
    (apply symbol? (list (quote two)))

    is *not* the same as typing on the REPL

    (symbol? two)

    symbol? is not a special function. So we evaluate its arguments :
    `` two ''.
    Bang! ERROR 8010.
    8010 : Symbol not in environment

    My test succeeds if we
    (def! two 2)
    2

    (apply number? (list two) )
    true

    I cannot reasonably interpret the specification such that the
    given test succeeds.

    (apply symbol? (list (quote(quote two)))
    gives true if I test it.

    If you had to jump through hoops like that , apply would be a lot
    less useful. Hence I'm thinking that the MAL specification is inaccurate.

    --
    From a slasher to a comedy to a sci-fi, is there anything that this
    franchise hasn't done? Yeah, a horror musical. Do that for twentieth
    film in the franchise, if you can make it up to that point.
    www.imdb.com/review/rw4741732

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kaz Kylheku@21:1/5 to albert@cherry on Thu Sep 21 14:02:40 2023
    On 2023-09-21, albert@cherry.(none) (albert) <albert@cherry> wrote:
    (apply symbol? (list (quote two))
    We arrive at the list to be evaluated
    (<#4623388> <two>) where #4623388 is the actual function symbol? refers to.

    This is an abstract structure tree: a list consisting of a a function
    and a symbol.

    Now we are supposed to evaluate this list.

    No, that would be a double evaluation.

    In a Lisp-1 dialect,

    (apply fun (list a b c))

    is the same as

    (fun a b c)

    You're talking about:

    ((eval fun) (eval (list a b c)))

    apply is an ordinary function. After evaluating the arguments
    we have these items

    (#<4580123> #<4623388> (two))
    ^ ^
    apply symbol?

    we are now ready to call the function: we call #<4580123>,
    which is apply, passing it #<4623388> and (two).

    apply doesn't eval anything: apply takes the list (two) and spreads
    it into individual arguments, which are passed to #<4623388>.

    The expectation that (apply symbol? (list two)) will yield
    true requires either very weird semantics that depart far from
    classic Lisp, or else that two is a variable which holds a symbol.

    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca
    NOTE: If you use Google Groups, I don't see you, unless you're whitelisted.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From none) (albert@21:1/5 to 864-117-4973@kylheku.com on Fri Sep 22 10:51:45 2023
    In article <20230921065214.723@kylheku.com>,
    Kaz Kylheku <864-117-4973@kylheku.com> wrote:
    On 2023-09-21, albert@cherry.(none) (albert) <albert@cherry> wrote:
    (apply symbol? (list (quote two))
    We arrive at the list to be evaluated
    (<#4623388> <two>) where #4623388 is the actual function symbol? refers to. >>
    This is an abstract structure tree: a list consisting of a a function
    and a symbol.

    Now we are supposed to evaluate this list.

    No, that would be a double evaluation.

    In a Lisp-1 dialect,

    (apply fun (list a b c))

    is the same as

    (fun a b c)

    You're talking about:

    ((eval fun) (eval (list a b c)))

    apply is an ordinary function. After evaluating the arguments
    we have these items

    (#<4580123> #<4623388> (two))
    ^ ^
    apply symbol?

    we are now ready to call the function: we call #<4580123>,
    which is apply, passing it #<4623388> and (two).

    apply doesn't eval anything: apply takes the list (two) and spreads
    it into individual arguments, which are passed to #<4623388>.
    What we do with #<4623388>, is that not called evaluation?

    I attached the property that a procedure is special or normal
    to the underlying procedure of `symbol? not to `symbol? itself.
    Is that correct?


    The expectation that (apply symbol? (list two)) will yield
    true requires either very weird semantics that depart far from
    classic Lisp, or else that two is a variable which holds a symbol.

    That was a mistake. See my separate post.
    (apply symbol? (list (quote two)))

    Kaz
    --
    Don't praise the day before the evening. One swallow doesn't make spring.
    You must not say "hey" before you have crossed the bridge. Don't sell the
    hide of the bear until you shot it. Better one bird in the hand than ten in
    the air. First gain is a cat spinning. - the Wise from Antrim -

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From none) (albert@21:1/5 to albert on Fri Sep 22 10:39:40 2023
    In article <nnd$76e3788b$0d113101@627a67ea51c23339>,
    none) (albert <albert@cherry.> wrote:
    Implementing mal according to https://github.com/kanaka/mal
    I have problems with the implementation of apply.

    (apply symbol? (list two) )
    should give true, but this test fails.

    Sorry I have goofed.
    The test in mal is actually,
    (apply symbol? (list (quote two)) )

    Kaz noticed that in his last line.

    My conclusion is that `apply' is not a normal function but special.
    It follows its own rules whether things should be evaluated.
    The problem is that the last parameters is a list, and
    I cannot pass a list without involking the (list..) construction
    In my book that is an evaluation of the list procedure called
    #2189218 whatever. So the second parameter is to be evaluated.

    What I understand is that `symbol? has a bald underlying procedure.
    `apply takes care that this procedure is called with the elements
    of list.

    Groetjes Albert
    --
    Don't praise the day before the evening. One swallow doesn't make spring.
    You must not say "hey" before you have crossed the bridge. Don't sell the
    hide of the bear until you shot it. Better one bird in the hand than ten in
    the air. First gain is a cat spinning. - the Wise from Antrim -

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From none) (albert@21:1/5 to 864-117-4973@kylheku.com on Fri Sep 22 14:52:32 2023
    In article <20230921065214.723@kylheku.com>,
    Kaz Kylheku <864-117-4973@kylheku.com> wrote:
    On 2023-09-21, albert@cherry.(none) (albert) <albert@cherry> wrote:
    (apply symbol? (list (quote two))
    We arrive at the list to be evaluated
    (<#4623388> <two>) where #4623388 is the actual function symbol? refers to. >>
    This is an abstract structure tree: a list consisting of a a function
    and a symbol.

    Now we are supposed to evaluate this list.

    No, that would be a double evaluation.

    That clears up nothing to me.
    lisp does double evaluations all the time.
    Suppose you have `fx a user defined function.
    (fx 1 2)
    The first item of the list is not a function, we are not happy thus:
    step 1 evaluate fx, the result is a list.
    The first item of the list is not a function, we are not happy thus:
    step 2 evaluate the list, the result is a function
    Now we are in a position to tackle (#111 1 2)
    Is that not a third evaluation then what is it?


    In a Lisp-1 dialect,

    (apply fun (list a b c))

    is the same as

    (fun a b c)

    You're talking about:

    ((eval fun) (eval (list a b c)))

    apply is an ordinary function. After evaluating the arguments
    we have these items

    fun is a symbol. It *got* to be evaluated, if we want the underlying
    function. What am I missing here?


    (#<4580123> #<4623388> (two))
    ^ ^
    apply symbol?

    we are now ready to call the function: we call #<4580123>,
    which is apply, passing it #<4623388> and (two).

    apply doesn't eval anything: apply takes the list (two) and spreads
    it into individual arguments, which are passed to #<4623388>.

    I managed to
    (apply symbol? (list (quote two)))
    to succeed giving true,
    passing the symbol `two to the now disembodied symbol?
    by relying on functions in the underlying implementation language.

    That is no solution, you can't pass arguments in lisp!
    You can only evaluate lists, or more precisely you got to put
    the function and arguments into a list
    The following tests now fails:
    ;; Testing apply function with user functions
    (apply (fn* (a b) (+ a b)) (list 2 3))
    You can abstract the fn* in a disembodied function #1222
    but it is supposed to be in a list, such as
    (#1222 3 4) otherwise the function can not find its arguments
    to fill it in on the places a and b.
    Now the story goes on. #1222 doesn't know better better than to
    evaluate its arguments and the problem only shifts.

    Groetjes Albert





    --
    Kaz
    --
    Don't praise the day before the evening. One swallow doesn't make spring.
    You must not say "hey" before you have crossed the bridge. Don't sell the
    hide of the bear until you shot it. Better one bird in the hand than ten in
    the air. First gain is a cat spinning. - the Wise from Antrim -

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kaz Kylheku@21:1/5 to albert@cherry on Fri Sep 22 14:57:00 2023
    On 2023-09-22, albert@cherry.(none) (albert) <albert@cherry> wrote:
    In article <20230921065214.723@kylheku.com>,
    Kaz Kylheku <864-117-4973@kylheku.com> wrote:
    On 2023-09-21, albert@cherry.(none) (albert) <albert@cherry> wrote:
    (apply symbol? (list (quote two))
    We arrive at the list to be evaluated
    (<#4623388> <two>) where #4623388 is the actual function symbol? refers to.

    This is an abstract structure tree: a list consisting of a a function
    and a symbol.

    Now we are supposed to evaluate this list.

    No, that would be a double evaluation.

    In a Lisp-1 dialect,

    (apply fun (list a b c))

    is the same as

    (fun a b c)

    You're talking about:

    ((eval fun) (eval (list a b c)))

    apply is an ordinary function. After evaluating the arguments
    we have these items

    (#<4580123> #<4623388> (two))
    ^ ^
    apply symbol?

    we are now ready to call the function: we call #<4580123>,
    which is apply, passing it #<4623388> and (two).

    apply doesn't eval anything: apply takes the list (two) and spreads
    it into individual arguments, which are passed to #<4623388>.
    What we do with #<4623388>, is that not called evaluation?

    There are two apply calls here. One of them is conceptual (it need
    not be literally done that way). When evaluation notices a function
    form (f ...), conceptually, that can be handled via the apply function.
    All constituent expressions are evaluated and then apply can be used
    to call the function f with those arguments. That apply is part of
    evaluation, as a subroutine.

    Here we have (apply ...). So expressions are evaluated and arguents
    are applied to the apply function.

    That apply function is external; it has its own evaluations going on
    inside but they are not part of the evaluation of the
    (apply fun (list a b c)) expression.

    We are not walking the syntax of the apply implementation; it could be
    coded in machine langauge.

    In any case, what apply does to the symbol? function is called
    application.

    I attached the property that a procedure is special or normal
    to the underlying procedure of `symbol? not to `symbol? itself.
    Is that correct?

    Not sure what you mean. In traditional Lisps, in fact the difference
    between kinds of procedures in the evaluation model, like EXPR vs SUBR
    in very old Lisp or macro expander versus ordinary function in Common
    Lisp, those differences are not attached to the function, but to the
    binding. A macro-expanding lambda doesn't know it's a macro-expanding
    lambda.

    apply isn't "special" in any way, except that implementations of apply
    are usually privy to the implementation of functions. apply has to have
    the know how to be able to take a function and list, and spread the list
    into function arguments to which the function is applied.

    If you take a Lisp dialect and remove apply (not necessarily remove it physically, but make it inaccessible to programs) there may be no other
    way for a program to bring back apply other than this:

    (define (apply fun . args)
    (eval `(,fun ,@args)))

    We work around the missing apply by generating code and feeding it to
    eval, which somehow knows how to apply functions to arguments.

    Needless to say, the real apply doesn't have to do things via eval; it
    can be a lower-level procedure (e.g. coded in machine language) which
    knows how to manipulate function calls.

    Since all we do is call apply in the same way as we call any other
    function, there is nothing special about it from the caller's point of
    view.

    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca
    NOTE: If you use Google Groups, I don't see you, unless you're whitelisted.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kaz Kylheku@21:1/5 to albert@cherry on Fri Sep 22 15:16:38 2023
    On 2023-09-22, albert@cherry.(none) (albert) <albert@cherry> wrote:
    In article <20230921065214.723@kylheku.com>,
    Kaz Kylheku <864-117-4973@kylheku.com> wrote:
    On 2023-09-21, albert@cherry.(none) (albert) <albert@cherry> wrote:
    (apply symbol? (list (quote two))
    We arrive at the list to be evaluated
    (<#4623388> <two>) where #4623388 is the actual function symbol? refers to.

    This is an abstract structure tree: a list consisting of a a function
    and a symbol.

    Now we are supposed to evaluate this list.

    No, that would be a double evaluation.

    That clears up nothing to me.
    lisp does double evaluations all the time.

    Actually, no, not implicitly. If something is multiply evaluated, it's
    because you coded extra evaluations into it.

    Suppose you have `fx a user defined function.
    (fx 1 2)
    The first item of the list is not a function, we are not happy thus:
    step 1 evaluate fx, the result is a list.
    The first item of the list is not a function, we are not happy thus:
    step 2 evaluate the list, the result is a function
    Now we are in a position to tackle (#111 1 2)
    Is that not a third evaluation then what is it?

    While that is possible, I don't know of any Lisp dialect which
    does this kind of iteration.

    The second and subsequent rounds of evaluation would be working
    with run-time data: whatever value is pulled out of the fx binding.

    Evaluating that would be a possible security issue.

    Lisps are compiled languages; only the first evaluation round could be compiled, unless the compiler can deduce the value of fx. Otherwise the subsequent evaluation rounds would have to be promoted to run-time.


    In a Lisp-1 dialect,

    (apply fun (list a b c))

    is the same as

    (fun a b c)

    You're talking about:

    ((eval fun) (eval (list a b c)))

    apply is an ordinary function. After evaluating the arguments
    we have these items

    fun is a symbol. It *got* to be evaluated, if we want the underlying function. What am I missing here?

    That once that takes place, the resulting #<4623388> object isn't
    evaluated any more.



    (#<4580123> #<4623388> (two))
    ^ ^
    apply symbol?

    we are now ready to call the function: we call #<4580123>,
    which is apply, passing it #<4623388> and (two).

    apply doesn't eval anything: apply takes the list (two) and spreads
    it into individual arguments, which are passed to #<4623388>.

    I managed to
    (apply symbol? (list (quote two)))
    to succeed giving true,
    passing the symbol `two to the now disembodied symbol?
    by relying on functions in the underlying implementation language.

    That is no solution, you can't pass arguments in lisp!

    Well, that's right; you can pass arguments in the implementation of
    Lisp, such as inside primitive procedures like apply and funcall.

    The classic description of Lisp eval in Lisp itself assumes that a
    primitive procedure apply is available, which doesn't have to be
    written.

    That description itself is evalued somehow, by an existing
    primitive eval. That eval somehow knows how to perform the function
    calls that occur in the syntax of the eval-in-Lisp source code.

    That eval-in-Lisp code itself knows how to to do the same thing,
    via the apply helper function.

    You can only evaluate lists, or more precisely you got to put
    the function and arguments into a list
    The following tests now fails:
    ;; Testing apply function with user functions
    (apply (fn* (a b) (+ a b)) (list 2 3))
    You can abstract the fn* in a disembodied function #1222
    but it is supposed to be in a list, such as
    (#1222 3 4) otherwise the function can not find its arguments
    to fill it in on the places a and b.
    Now the story goes on. #1222 doesn't know better better than to
    evaluate its arguments and the problem only shifts.

    #1222 should only need to access its arguments. In the body (+ a b), a
    and b are just local variables that have been given values in by the application of that function. Evaluating a just means retrieving the
    value of a, not evaluating the original expression.

    In a purely interpreted Lisp, a function's representation retains
    the source code pieces, like the names of the arguments and the body
    as-is (usually after macro-expansion).

    The apply procedure, when it sees such an interpreted function, has to
    perform the binding: extract the function object's list of parameter
    names, and create an environment which binds them to the argument
    values. Then it evaluates the body in that environment using an
    evaluator. (That evaluator is not necessarily the one you are writing!)
    If the funtion is compiled, or written in a lower level language by
    hand, such as C or assembly, then the process of calling it may
    be quite different. Apply has to generate a function call in that
    language. It may involve pushing values on the stack, or preparing
    them in registers, and getting a result value or values in a certain
    way like from certain registers or on the stack.


    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca
    NOTE: If you use Google Groups, I don't see you, unless you're whitelisted.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)