public inbox for kawa@sourceware.org
 help / color / mirror / Atom feed
From: Panicz Maciej Godek <godek.maciek@gmail.com>
To: Per Bothner <per@bothner.com>
Cc: kawa@sourceware.org
Subject: Re: Having Named Parts
Date: Fri, 2 Dec 2022 00:15:07 +0100	[thread overview]
Message-ID: <CAMFYt2Yg5hpewUz8iNTx-Qzz+AZAunH-=gtA6ybTfJ4jRNbP5Q@mail.gmail.com> (raw)
In-Reply-To: <eda2785b-930d-4b0e-bb45-3ec6dbe63f7f@bothner.com>

[-- Attachment #1: Type: text/plain, Size: 7193 bytes --]

czw., 1 gru 2022 o 23:16 Per Bothner <per@bothner.com> napisał(a):

>
>
> On 12/1/22 03:19, Panicz Maciej Godek via Kawa wrote:
> > I've been trying to build a simple wrapper for a hash table,
> > that I call Bundle, such that
> >
> > (Bundle x: 5 y: 10)
> >
> > would return a bundle object, let's call it b, so that I could refer to
> its
> > fields using
> >
> > b:x
>
> That would be a nicer syntax, but there could be some problems combining
> the concepts of hash-table (extensible with arbitrary keys, not
> necessarily strings)
> and structures (with a fixed set of keys).  JavaScript does it, and it
> does make
> things more convenient.
>
> There are a lot of issues to consider. Should key names be strings or
> symbols?
> What about keys that are not names (keys or strings)?


I think they have to be Strings, because of how the HasNamedPart interface
is defined.


>   How does this conflict
> with existing usage of colon-notation, and how do we deal with those?
>
> So I'm not sure if hash tables should implement HasNamedParts by default.
>
> No, I don't think so either.
But I think it would be nice if Kawa facilitated adding such classes.

For the development of GRASP, I have built a macro called define-type
<https://github.com/panicz/grasp-android/blob/master/stages/retreat/GRASP/src/define-type.scm>,
which is used for defining record-like classes.
It is used like this:

(define-type (Extent width: real height: real))

And it defines a class that can be instantiated as

(define e ::Extent (Extent width: 10 height: 20))

I also have a pattern matcher which supports this notation, so I can write
things like

(match e
  ((Extent width: size height: size)
   'square)
  ((Position width: w height: h)
   'rectangle))

I like it way more than any SRFI record proposals I've seen.

Also, with Kawa's syntax extensions I can write

(set! e:width 50)

and it Just Works. I find this experience very satisfying (to be honest,
I'm quite surprised that many modern languages like Java or Haskell have
much worse capabilities of defining structures than the C language).

And I thought it would be nice to have a more flexible record-like type
that I call Bundle (referring to David Hume's "bundle theory of meaning")
-- so that it would also work in the context of pattern matching etc.

I don't expect it to be the main interface to hash tables.

An alternative is to use function-call notation, like we do for vectors:
>    (TABLE KEY)
>    (set! (TABLE KEY) VALUE)
> This has the advantage that it does't conflict with other uses of
> colon-notation.
> However, it doesn't provide a constructor syntax "for free".
>
>
Yes, I actually use that a lot in GRASP.
I have defined a bunch of macros such as define-mapping
<https://github.com/panicz/grasp-android/blob/master/stages/retreat/GRASP/src/mapping.scm>
(which uses a normal hash table underneath) or define-property
<https://github.com/panicz/grasp-android/blob/master/stages/retreat/GRASP/src/define-property.scm>
(which uses a weak-key table) that is used like this:

(define-property (dotted? cell::cons)::boolean #f)

The nice thing about this is that it lets me provide the default value very
naturally (and I could also signal error for missing keys).
I also have a variant of weak-key which can accept more than one argument,
that is called define-cache
<https://github.com/panicz/grasp-android/blob/master/stages/retreat/GRASP/src/define-cache.scm>
(and
it's achieved by means of "currying", i.e. constructing hash tables that
return hash tables etc.)

But the difference between those hash tables and bundles is that bundles
are meant to be externalizable, whereas properties are essentially opaque.

I brought up these concerns on the mailing list years ago.  If someone can
> find these old message it might be helpful ...
>
> > I have found that Kawa offers a gnu.mapping.HasNamedParts interface which
> > facilitates value reference, ...s
> > The source code for the gnu.kawa.functions.SetNamedPart.apply3 method
> > reveals, that there was a plan for supporting this -- the method begins
> > with a commented-out fragment:
> >
> >      /*
> >      if (container implements HasNamedParts)
> >        return ((HasNamedParts) container).getNamedPart(part);
> >      */
> >
> > which wouldn't work with current Kawa, because the HasNamedParts
> interface
> > doesn't containt getNamedPart method, and instead it contains a method
> > called get. I think that this could be fixed by:
> > - adding a method Object set(String key, Object value) to the
> HasNamedParts
> > interface
> > - uncommenting and fixing the above snippet to invoke the above method.
>
> That is probably OK, except use 'put' instead of 'set' to be consistent
> with java.util.Map.
> Also, 'put' needs a default implementation, which should probably
> throw UnsupportedOperationException.  (Defaults were added in Java 8. It
> is probably
> OK to require Java 8 as a minimum at this point - though Android might be
> an issue.)
>
>
Actually Android SDK ships with a tool called d8, which is a replacement
for their dx converter,
which handles the Java 8 bytecode (I was even able to generate byte code
for API level 1
with it)


> Do compare with the getNamedPart and apply 2 method in GetNamedPart.
> They handles various extra cases, that might not be appropriate for a
> setter.
>
> > By the way, the interface also contains isConstant method, which doesn't
> > seem to be documented anywhere.
>
> isConstant(KEY) returns true is the binding for KEY is immutable.
> It is used to optimize namespace resolution.
>
>   I think that also - for consistency - the
> > interface should also provide a boolean hasPartNamed(String name) method.
> >
> > But this only solves one problem, and there's another one, namely - when
> I
> > try to initialize Bundle as, say
> >
> > (Bundle x: 5 y: 10)
> >
> > I get the following warnings:
> >
> > /dev/tty:6:20: warning - no field or setter 'x' in class Bundle
> > /dev/tty:6:20: warning - no field or setter 'y' in class Bundle
> >
> > These are issued from the build() method in
> > gnu.kawa.reflect.CompileBuildObject. It does seem that this class doesn't
> > take into account the existence of the HasNamedParts interface at all.
>
> That is probably the case.
>
> > Is there any way out of this situation?
>
> If there was a clean problem-free solution I would have already done so ...
> That doesn't mean we shouldn't have a better syntax for hash-tables,
> or that this is a dead end - but there are definitely a number of issues
> to consider.
>
>
 Again, I don't want to push for having an opinionated way of dealing with
hash tables.
I think it would be sufficient if Kawa could provide their users (or me in
particular :D)
with the means of creating various different solutions and experimenting
with them.

I think that supporting setters for HasNamedPart and in CompileBuildObject
would simply be consistent with the idea of the HasNamedPart interface,
and it doesn't seem to break anything

      reply	other threads:[~2022-12-01 23:15 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-12-01 11:19 Panicz Maciej Godek
2022-12-01 22:16 ` Per Bothner
2022-12-01 23:15   ` Panicz Maciej Godek [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAMFYt2Yg5hpewUz8iNTx-Qzz+AZAunH-=gtA6ybTfJ4jRNbP5Q@mail.gmail.com' \
    --to=godek.maciek@gmail.com \
    --cc=kawa@sourceware.org \
    --cc=per@bothner.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).