Extending functional call syntax for Sequences to include Maps

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

Extending functional call syntax for Sequences to include Maps

Sourceware - kawa list mailing list
Hello,

I've been reading the Kawa docs quite seriously when I was looking to learn
the Pattern design. I noticed that Sequences implement Procedure, as shown
here in the documentation:

To extract an element from Scheme sequence of type stype there is usually a
function stype-ref. For example:
(define vec1 (vector 5 6 7 8))
(vector-ref vec1 2) ⇒ 7


More concisely, you can use (Kawa-specific) function call syntax:

(vec1 3) ⇒ 8


Which is pretty neat (and reminds me of what they did in Clojure also,
http://clojure-doc.org/articles/language/functions.html#sets-as-functions).

I was a little disappointed when I found out that this doesn't work for
Maps, which is also something Clojure allows [0]:

;; This is Clojure not Scheme

({:age 42 :name "Joe"} :name)     ; ⇒ "Joe"
({:age 42 :name "Joe"} :age)      ; ⇒ 42
({:age 42 :name "Joe"} :unknown)  ; ⇒ nil


[0]
http://clojure-doc.org/articles/language/functions.html#maps-as-functions

Duncan.
Reply | Threaded
Open this post in threaded view
|

Re: Extending functional call syntax for Sequences to include Maps

Per Bothner
On 7/3/20 2:24 PM, Duncan Mak via Kawa wrote:

> More concisely, you can use (Kawa-specific) function call syntax:
>
> (vec1 3) ⇒ 8
>
>
> I was a little disappointed when I found out that this doesn't work for
> Maps, which is also something Clojure allows [0]:
>
> ;; This is Clojure not Scheme
>
> ({:age 42 :name "Joe"} :name)     ; ⇒ "Joe"
> ({:age 42 :name "Joe"} :age)      ; ⇒ 42
> ({:age 42 :name "Joe"} :unknown)  ; ⇒ nil

I vaguely remember discussing this some years ago, and I think the main
(conceptual) problem is how to handle arguments with no binding, i.e.
the 3rd case above.  By analogy with sequences, it should throw an
exception - which may not be the most convenient

I mentioned a couple of possible approaches, but I don't recall
what they were.  I think I was leaning towards a way to specify
a default value - and throw an exception when no default was specified.

I haven't been able to find that email, so far.

A possibly solution:

(htab key [default])

If there is no entry for key in htab, then default is returned
if specified; otherwise an exception is thrown.

You should also be able to do:

(set! (htab key) new-value)
--
        --Per Bothner
[hidden email]   http://per.bothner.com/
Reply | Threaded
Open this post in threaded view
|

Re: Extending functional call syntax for Sequences to include Maps

Sourceware - kawa list mailing list
I think with an optional keyword argument, this could look quite nice!

(aMap "key" default: "default value")

The keyword could be 'default', or even 'or'.

(aMap 'key or: "empty")


On Fri, Jul 3, 2020 at 6:05 PM Per Bothner <[hidden email]> wrote:

> On 7/3/20 2:24 PM, Duncan Mak via Kawa wrote:
> > More concisely, you can use (Kawa-specific) function call syntax:
> >
> > (vec1 3) ⇒ 8
> >
> >
> > I was a little disappointed when I found out that this doesn't work for
> > Maps, which is also something Clojure allows [0]:
> >
> > ;; This is Clojure not Scheme
> >
> > ({:age 42 :name "Joe"} :name)     ; ⇒ "Joe"
> > ({:age 42 :name "Joe"} :age)      ; ⇒ 42
> > ({:age 42 :name "Joe"} :unknown)  ; ⇒ nil
>
> I vaguely remember discussing this some years ago, and I think the main
> (conceptual) problem is how to handle arguments with no binding, i.e.
> the 3rd case above.  By analogy with sequences, it should throw an
> exception - which may not be the most convenient
>
> I mentioned a couple of possible approaches, but I don't recall
> what they were.  I think I was leaning towards a way to specify
> a default value - and throw an exception when no default was specified.
>
> I haven't been able to find that email, so far.
>
> A possibly solution:
>
> (htab key [default])
>
> If there is no entry for key in htab, then default is returned
> if specified; otherwise an exception is thrown.
>
> You should also be able to do:
>
> (set! (htab key) new-value)
> --
>         --Per Bothner
> [hidden email]   http://per.bothner.com/
>


--
Duncan.
Reply | Threaded
Open this post in threaded view
|

Re: Extending functional call syntax for Sequences to include Maps

Jamison Hope-2
In reply to this post by Per Bothner
On Fri, Jul 3, 2020 at 6:05 PM Per Bothner <[hidden email]> wrote:

>
> On 7/3/20 2:24 PM, Duncan Mak via Kawa wrote:
> > More concisely, you can use (Kawa-specific) function call syntax:
> >
> > (vec1 3) ⇒ 8
> >
> >
> > I was a little disappointed when I found out that this doesn't work for
> > Maps, which is also something Clojure allows [0]:
> >
> > ;; This is Clojure not Scheme
> >
> > ({:age 42 :name "Joe"} :name)     ; ⇒ "Joe"
> > ({:age 42 :name "Joe"} :age)      ; ⇒ 42
> > ({:age 42 :name "Joe"} :unknown)  ; ⇒ nil
>
> I vaguely remember discussing this some years ago, and I think the main
> (conceptual) problem is how to handle arguments with no binding, i.e.
> the 3rd case above.  By analogy with sequences, it should throw an
> exception - which may not be the most convenient
>
> I mentioned a couple of possible approaches, but I don't recall
> what they were.  I think I was leaning towards a way to specify
> a default value - and throw an exception when no default was specified.
>
> I haven't been able to find that email, so far.

I suspect you're remembering this conversation we had five (!) years ago:
https://sourceware.org/pipermail/kawa/2015q1/006284.html

You were leaning toward throwing an exception on no-default, and I was
leaning toward returning #!null for simplicity/consistency with Java,
and also because #!null is treated as false, which is like what
assq/assv/assoc and memq/memv/member return for an absent key.

-J

>
> A possibly solution:
>
> (htab key [default])
>
> If there is no entry for key in htab, then default is returned
> if specified; otherwise an exception is thrown.
>
> You should also be able to do:
>
> (set! (htab key) new-value)
> --
>         --Per Bothner
> [hidden email]   http://per.bothner.com/



--
Jamison Hope
Reply | Threaded
Open this post in threaded view
|

Re: Extending functional call syntax for Sequences to include Maps

Per Bothner
On 7/15/20 11:44 AM, Jamison Hope wrote:
> I suspect you're remembering this conversation we had five (!) years ago:
> https://sourceware.org/pipermail/kawa/2015q1/006284.html

Only five? I see ChangeLog entries with your name going back to 2009 ....

> You were leaning toward throwing an exception on no-default, and I was
> leaning toward returning #!null for simplicity/consistency with Java,
> and also because #!null is treated as false, which is like what
> assq/assv/assoc and memq/memv/member return for an absent key.

I still feel more comfortable with throwing an exception if KEY is invalid
in the (HMAP KEY) case.  I think passing a default argument
doesn't really need a keyword - (HMAP KEY DEFAULT) looks good to me.

I don't expect I'll be implementing this feature anytime soon - perhaps
an interesting project for someone?  It's not completely trivial
because of the compile-time handling of "ApplyToArgs".

You also mentioned hash literals.  I'm not as keen on a syntax
that only works for literal maps - I'd like an elegant syntax that
works for keys and values that are expressions evaluated at run-time.
Conceptually similar to the sequence syntax:
   [E0 E1 ... ELAST]

One approach is to use quasi-quotation, though I think that's a bit ugly.
--
        --Per Bothner
[hidden email]   http://per.bothner.com/