Something like this? https://play.golang.com/p/rhu9PX9GSbp

On Saturday, April 2, 2022 at 5:41:52 AM UTC+7 sam.a....@gmail.com wrote:

> Point-free programming, or "tacit programming",  is a convention that 
> highlights the intent without syntactic noise. 
>
> For those unfamiliar, wikipedia: 
> https://en.wikipedia.org/wiki/Tacit_programming
>
> I want better function composition. "Write a helper function to route 
> values out to values in, like a normal person." Sure, but who needs Go when 
> you have C, eh? A tacit sugaring merely provides a lexically distinctive 
> means to indicate the intent that function f0 should be called with the 
> return value of f1, and f1 of f2, and so on, with reduced syntax.
>
> There are a couple layers here, there's an easy win, a possible next step, 
> and well, madness.
>
> A. Go uses a thin-arrow, "<" + "-", as a receive/send operator and to 
> signify directionality of a channel. This same operator could be used like 
> so, "c := a <- b()" to assert the following:
>     1. Token "a" resolves to a function pointer
>     2. Token "b" returns none, one, or many values, such that "a(b())" is 
> legal.
>     3. Token "c" can legally be assigned the value of the desugared 
> expression.
> This suggestion imposes ambiguity between the meaning of "(chan 
> int)(x)<-y(z)" and "(func(int)int)(x)<-y(z)", and I have chaotic intuitions 
> about the meaning of "(func(int)int)(x) <- (chan int)(y)", or even 
> "(func(int)int)(x) <- (chan int)(y) <- z", but x(<-y) is clearly 
> (func[T](T)T)(x)(<-(chan[T] T)(y)). A minimally disruptive solution, then, 
> is to assert that the tip of such a tacit chain must be a full-syntax 
> invokation, e.g. for "f0 <-...f<N-1> <- ?", only "f<N>(...)" is valid. This 
> means expressions like "c0 <- f0 <- f1(f2 <-f3(<-c1))" are unambiguous 
> without a mountain of ellipses.
>
> B. At cost of introducing a new concept for Go entirely, it would be 
> convenient to declare a function as "f0 := f1 <- f2 <- f3", resolving as 
> suggested by the statement: "reflect.TypeOf(f0) == 
> reflect.FuncOf([]reflect.Type{reflect.TypeOf(f3).In(0), ..<etc>}, 
> []reflect.Type{reflect.TypeOf(f1).Out(0), ...<etc>})". The straightforward 
> path to implementation would resolve that naively, as suggested by the 
> following: "f0 := func[T handWaving.inT, U handWaving.outT](a... T) (...U) 
> {return f1(f2(f3(a...)))}". A statement like "go f0 <- f1 <-f2 <- f3", 
> assuming "go func[T handWaving.inT](a...T) {f0(f3(a...));}" is legal, would 
> be an attractive pattern.
>
> C. Naively, point B suggests that the functions thus concatenated could be 
> assembled as to preallocate the stack for the entire concatenation, 
> omitting the allocations and moves/copies between function calls, and 
> rather writing the return values to the stack for the predecessor function, 
> by analogy, like a reverse closure or a heterogenous recursion. For the 
> example "f0 := f1 <- f2 <- f3", because I expect that statement to only be 
> legal if "f1(f2(f3(..args..)))" is legal, the out-signature of f3 is 
> assignment-compatible with the in-signature of f2, and f2 to f1. Concerns 
> such as an element in the concatenation being recursive, blocking, or 
> corrupting only apply to the function at stack-head; pre-allocating even a 
> potentially large stack exposes only risk shared with allocating the same 
> stack progressively, but with lower instructional segmentation. A possible 
> but unlikely edge-case, if for some reason, a generic function cannot be 
> appropriately stenciled, the optimization being suggested might only 
> partially be applied, or else not applied at all. 
>
> Ellipses are basically universal for "I give you control, but I expect it 
> back". Loops don't give up control, rather push it on a swing like a child. 
> Go-func commissions an agent, expecting no control. Point A would change 
> the expression somewhat, but by requiring the head of a concatenation to be 
> an execution, the language of "I give, but I expect" is kept, but uses the 
> existing language of sending on channels,  "B to A, your turn A", and is 
> suggested as unambiguously extending the "I give, I expect" agreement 
> backwards towards the tail. The symbols suggested are certainly not sacred, 
> either.
>
> Point B and C are harder to recommend unequivocally, but could be potently 
> powerful tools for communicating very long but uncomplicated calls. Point B 
> has very few downsides, but represents introduction of a case where a human 
> might understand an expression differently than a parser, while Point C 
> introduces a layer of complexity to serve a use case that, for better or 
> worse, could serve to push a new idiom onto the Gopher community. 
>
> These three points present no risk to the Go 1 compatibility promise, but 
> I will admit before anyone else that I haven't proven that Point C is worth 
> the investment, and I expect some difficult questions about Point B.
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/82780772-5819-412b-a238-87f53ec22f77n%40googlegroups.com.

Reply via email to