OK, I have been thinking more about this, and also reading the comments on-wiki, which have been very enlightening and sketched out a good solution (basically the on Adam hinted at in this thread too).

https://meta.wikimedia.org/wiki/Talk:Abstract_Wikipedia/Function_model#Make_Z7_more_uniform 

So the function call we used as a running example could look like this:

Z1K1: Z7
Z7K1: Z144
Z7K2:
  Z1K1: Z824(Z144)
  Z144K1: "Wiki"
  Z144K2: "data"

Z7K1 points to the Function to be evoked, and has Z8/Function as the value type, and so we can use Z144, which is a Function as the value.
Z7K2 points to the arguments.
The type of Z7K2 is using the Z824 Function on the Function. Z824 basically takes a Z8/Function and returns a Z4/Type (basically turning the Z17/argument declarations to Z3/keys, mostly).

There's a little bit of repetition (Z144 is mentioned twice, as the value of Z7K1 as well as in the Z1K1 of the Z7K2), but that also allows us to break any potential recursion by materializing the the result of Z824 (which might be necessary to express Z824(Z824) (or not, we'll see)).

I think that should solve this conundrum.

Again thanks everyone. If there are no complaints here or on-wiki, I will update the Function Model after the weekend.

Thanks,
Denny


On Mon, Oct 19, 2020 at 6:35 PM Denny Vrandečić <dvrandecic@wikimedia.org> wrote:
In principle, I would like Z7 to be able to appear almost everywhere. Particularly, they can be a function call to create a different content in some place. (That's something I would like to steal from lisp)

One example: I noticed that one problem with my proposal is that in

Z1K1: Z144

the problem is that Z144 is actually a Z8/Function, not a Z4/Type! But Z1K1 should be types.

So what we would need would be a function that takes a Function and returns a type, say Z824, and that can now help us (in tighter syntax):

Z1K1: Z824(Z144)

(Well, in reality, that would be

Z1K1:
  Z1K1: Z7
  Z7K1:
    Z1K1: Z7
    Z7K1:
      Z1K1: Z824
     Z824K1: Z144

Ah, gnarg, that's recursive!! Z824 is again a function!

And that's when you notice halfway through writing your answer that there is a mistake in your thinking.

In order to break the recursion, at least Z824(Z824) would need to be materialized, so we can call it directly.
(And that's why in Lambda Calculus there is a recursion operator)


Sorry for my half-baked thoughts.









On Mon, Oct 19, 2020 at 9:16 AM Arthur Smith <arthurpsmith@gmail.com> wrote:
So I was wondering, can we list the contexts in which we anticipate function calls happening?
There's the definition of another function - an implementation, where the arguments (values for the keys) are derived somehow from the arguments to the function being defined
Or in running a test, we call a function with certain arguments and expect a certain result to compare to
Or in an actual call context (API?) where an external user wants to use that function to generate a result

Are there other cases we can anticipate now? Maybe we could run through what the ZObjects would look like in each context and then see what's really needed there?

   Arthur

On Sun, Oct 18, 2020 at 11:33 PM Subramanya Sastry <ssastry@wikimedia.org> wrote:

In general, it seems better to use explicit typing (via a Z7 object to indicate something is a function call) vs. implicit typing (if Z1K1 is a function call, then this is a function call).

It might potentially lead to simpler error semantics. What if a typo / accidental keystroke changes "Z142" to "Z12" and Z12 were not a function? Then, suddenly the behavior of wherever this object was used would change mysteriously .. in some cases, it might error immediately (because of the context), and in other cases, it might fail downstream and in other cases, it may lead to incorrect output.

With an explicit Z7 type, there is no scope for such confusion and you get immediate failure (assuming validation is enabled) on typos / errors.

Subbu.

On 10/15/20 6:12 PM, Denny Vrandečić wrote:
So just thinking out loud.

I was thinking about that too - do we even need the Z7?

The advantage of having an explicit Z7 is that we know immediately that this is an object that needs to be treated specially. On the other side, that seems to be only one removed - we just need to look up the type of Z142, and if it is Function, well, there we are!

The other advantage of using an explicit Z7 is that we could use a Z142 without a Z7 embedding it like a quote in lisp. The Z7 unquotes and evaluates it.

So not sure if Z7 is needed. I would love to hear more thoughts. I have the sense that it would be really useful to keep the Z7, but I have trouble to say exactly why.




Regarding the Currying: that should not be a problem either way, though, if I understand right. So assume that we have a function curry Z78 and the concatenate function Z142.

Z1K1:
  Z1K1: Z7
  Z7K1:
    Z1K1: Z78
    Z78K1: Z142
    Z78K2: "Wiki"
K1: "data"

So here we use curry(concatenate, "Wiki"), which results in a function that takes a single string and prepends "Wiki" to it, so that would be read as curry(concatenate, "Wiki")("data")

Note that the K1 would need to be a local key as there is no global key that could be used, as the function is being created on the fly.

But please correct me if I misunderstood your comment on currying.



Thanks so much for your thoughts!

On Thu, Oct 15, 2020 at 5:34 AM Arthur Smith <arthurpsmith@gmail.com> wrote:
Hi Denny - this is interesting, but perhaps it means we don't even need the Z7 type at all? That is, just go with:

Z1K1: Z142
Z142K1: "Wiki"
Z142K2: "data"

So every instance of Z8 (function type) is itself a type whose instances are function calls? I'm wondering how either approach would allow for currying though... I guess that gets into function implementations? But at some level you'd want a function call that allowed for combining both Z142 keys and the key of the curried function. So there may still be a need for several different key prefixes within the same ZObject?

   Arthur

On Wed, Oct 14, 2020 at 7:16 PM Denny Vrandečić <dvrandecic@wikimedia.org> wrote:
This is a rather technical question. If you are not interested in the inner working of the function model, feel free to safely skip this one.

Currently, a function call is represented as follows (assume, Z142 is the concatenation function):
Z1K1: Z7
Z7K1: Z144
Z144K1: "Wiki"
Z144K2: "data"

If we use global keys, it would look like this:
Z1K1: Z7
Z7K1: Z144
K1: "Wiki"
K2: "data"

The local keys in this case get expanded against the Z7K1 value, not the Z1K1 value, as is the case for all other local keys. This makes it very different than all the other objects, and requires special handling.

The suggestion is to change the representation of function calls and make them more unified compared to the other entries, i.e. like this:

Z1K1: Z7
Z7K1:
  Z1K1: Z144
  Z144K1: "Wiki"
  Z144K2: "data"

So, instead of pulling the values into the Z7 object, we basically instantiate a function just like any other type, and wrap it into a Z7 to say that this is a function call. This needs one extra object, but it leads to much more uniform handling of objects.

Any thoughts?

Cheers,
Denny
_______________________________________________
Abstract-Wikipedia mailing list
Abstract-Wikipedia@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/abstract-wikipedia
_______________________________________________
Abstract-Wikipedia mailing list
Abstract-Wikipedia@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/abstract-wikipedia

_______________________________________________
Abstract-Wikipedia mailing list
Abstract-Wikipedia@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/abstract-wikipedia
_______________________________________________
Abstract-Wikipedia mailing list
Abstract-Wikipedia@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/abstract-wikipedia
_______________________________________________
Abstract-Wikipedia mailing list
Abstract-Wikipedia@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/abstract-wikipedia