I need some help with notation!
And perhaps theory. Here is the idea.
Felix has records with scoped labels. This means
you can have duplicate labels:
var r = (a=1, a=2, b=3, a=4);
Currently,
r.a
returns 1, that is, the projection a returns the first a it finds.
You can get the second a like this:
(r without a).a
[Thanks to Ryan for the without keyword]
However this is clearly messy! A more general notation
would be like:
r # a @ 0
However @ is not really the standard projection. Technically the
idea is that
#a selects a sequence of fields (NOT an actual tuple)
#5 selects the fifth one of the sequence
and
r.5 means r# _ . 5
> On 13 Dec 2015, at 04:59, Garrett Bluma <garret...@gmail.com> wrote:
>
> Thinking about this more, it seems like I was focused on projection over blank-named elements only. Which, if we ignore that there could be elements with actual names then it should work to treat them as tuples directly.
You’re missing the point. We can’t treat “the sequence of fields with the same name”
as a tuple. Because I’m trying to define a tuple as a RECORD which HAPPENS to
have all blank names. In other words, it’s a special case of a record. Which
means there are NO tuple operators: there is no index operator for tuples
because tuples no longer exist.
What I’m trying to do is define “scoped record operators” as axiomatic
and then *define* the usual tuple and record operators ON RECORDS
using them. For example:
(a=1,a=2,b-1) . 1 ==> ERROR, no field name “”
(a=1).b ==> ERROR, no field name “b”
(a=1,a=2).a ==> OK, field name a has at least one occurrence
This is all because the definition of a field projection by name is the
first found field or error, and the projection by index is the n’th
field named “”.
There are no tuples. There are no records with unique fields.
There is only ONE type: a scoped record (record with duplicate fields).
I need some help with notation!
And perhaps theory. Here is the idea.
Felix has records with scoped labels. This means you can have duplicate labels:
var r = (a=1, a=2, b=3, a=4);
Currently,
r.a
returns 1, that is, the projection a returns the first a it finds.
You can get the second a like this:
(r without a).a
[Thanks to Ryan for the without keyword]
However this is clearly messy!
A more general notation would be like:
r # a @ 0
where the a projection fetches ALL the a’s, and then the numerical index fetches the n’th one. This notation conflicts with the existing notation (which is the main problem I suspect).
But now here is another record:
(=1, =2, =3)
you see I left out the field label. We could just write that like this:
(1,2,3)
i.e. it is nothing more than a tuple! So using the above notation:
r # @ 0
would be 1, that is, we leave out the field name. We can view
#@
as tuple access. So the theoretical view is of two operators, a field projection returning a tuple of all the values of a given field and a tuple projection selecting one of them. The currect field projection is composed of the new field selector followed by a projection getting the first value. The current tuple projection becomes instead a field selector for the empty field followed by the new tuple projection.
1.) We already have a projection function (the dot operator and a number) and we should think twice about adding a second one that does the same thing.my_record # a @ 0is equivalent to(my_record # a).0
Yet the second one is the standard for projection for tuples. Also, how isr # @ 0intended to be different from this?r.0In my mind, they are functionally similar. In the #@ version, we are applying an operation to remove labels and then access an element by position. What if the projection on a named record could do this conversion automatically? That would simplify the language instead of encumbering it. The naive approach of just trying to get the 2nd element of a record could "just work".
2.) The # symbol is part of a group of operations that should be similar in appearance. I'm suggesting 'withonly' as a substitution.r with (metadata=(likes_ice_cream=True))r without metadatar withonly email_address // r # email_address in your notationThe # is just a little jarring. If we wanted to go with symbolic notation, I'd argue for something more arithmetic. Extension is like addition, exclusion is like subtraction, and isolation to a single name (or set of names) is like modulation.r + (metadata=(likes_ice_cream=True)) // "+" equivalent to "with"r - metadata // "-" equivalent to "without"r % email_address // "%" equivalent to "withonly"
given a blue number or a green number, just return me the blue
number with plain colour.
So, generalising the diagonal and codiagonal to n>2 instead of
n=2 for pairs, we use the generalised projection, and we can
recover the more specialised projections
--
You received this message because you are subscribed to the Google Groups "Felix Language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to felix-languag...@googlegroups.com.
To post to this group, send email to felix-l...@googlegroups.com.
Visit this group at https://groups.google.com/group/felix-language.
For more options, visit https://groups.google.com/d/optout.
Furthermore, why the hell does a record permit duplicate labels in the first place ?
> On 24 Jan 2016, at 04:48, srean <srean...@gmail.com> wrote:
>
> I have postponed understanding what row-polymorphism is about for now.
> May be someday.
Simple enough:
fun f[R] (x: (a:int | R) ) => (b=2 | x);
This function matches any record with a field named “a” of type int. It returns the same record with field b=2 added.
Unlike subtyping the “unspecified fields” are not lost, even though you don’t know what they are.
In the literature R above is a row. Which is just a list of field/type pairs. In Felix R is actually a record type not a row.
Its simple. If you have a class A with method X and a derived class B with method Y also,
then if you pass a B to a function expecting an A, you lose the Y method.
That’s subtyping.
With row polymorphism you don’t lose the Y method. You can’t use it.
But you can pass the whole object out of the function.
> But the function declares its return type. How can it return a different type?
fun[R] f (r: (x:int | R) ) => x,r;
The return type isn’t declared but it is
int * (x:int | R)
where R is the record type of the argument minus the x:int field.
It’s splitting the record into the x field and “all the rest” denoted by type variable R.
So roughly: subtyping uses slicing, row polymorphism uses splitting instead.
> On 27 Jan 2016, at 06:05, Sod Almighty <sod.al...@gmail.com> wrote:
>
> Isn’t this a function which can take an integer or an R?
No, the notation is taken from the academic literature, the “|” doesn’t
mean “or”.
> On 22 Nov 2018, at 02:37, Brandon Barker <brandon...@gmail.com> wrote:
>
> I know this is an old thread. But I can't help myself. I programmed in Scala for about three years, a bit less than half time, before beginning to wish that records (really, Scala case classes) and tuples were the same. Sometimes you want to treat data as a tuple, sometimes as a record.
In Felix they are the same type. However probably not quite what you were thinking of.
If a record has all blank field names .. its a tuple.
Also if a tuple has all the same type components, its an array.
Records can also have duplicate fields:
(a=1,a=2).a == 1
Functions which are written like:
fun f(x:int,y:double)
accept BOTH tuples:
f (1,2.1)
and records:
f (x=1,y=2.1)
Field names can be used to disabiguate function calls.
The order doesn’t matter if you use names, except for duplicates.
You can also have default arguments. You have to use records for
that to work.
An extension of records called “polyrecords” provides row polymorphism.
Unfortunately I can’t think of a syntax for getting all the field with a particular
name out of a record (as a tuple).
—
John Skaller
ska...@internode.on.net
--
You received this message because you are subscribed to the Google Groups "Felix Language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to felix-languag...@googlegroups.com.
To post to this group, send email to felix-l...@googlegroups.com.
Visit this group at https://groups.google.com/group/felix-language.
For more options, visit https://groups.google.com/d/optout.