Re: [go-nuts] Generic "nillable" constraint

2023-10-18 Thread 'Axel Wagner' via golang-nuts
On Wed, Oct 18, 2023 at 5:24 PM Jon Watte  wrote:

> I think "making all values comparable" is a worse change though (there's a
> reason they aren't comparable!)
>

FTR the proposal was not to make all values comparable, but to make all
values comparable to the predeclared identifier nil - similar to how,
currently, a lot of non-comparable values are comparable to the predeclared
identifier nil.


> and making everything comparable to nil without type qualification is
> better IMO.
>
> Sincerely,
>
> Jon Watte
>
>
> --
> "I find that the harder I work, the more luck I seem to have." -- Thomas
> Jefferson
>
>
> On Tue, Oct 17, 2023 at 10:25 PM Axel Wagner <
> axel.wagner...@googlemail.com> wrote:
>
>> On Wed, Oct 18, 2023 at 6:09 AM Jon Watte  wrote:
>>
>>> Circling back to this, because it came up today again.
>>>
>>> Here's the generic function I want to write. It comes up in a lot of
>>> function composition, which in turn comes up in a lot of interface adapters
>>> and such:
>>>
>>> func maybeAssign[T any](dst *T, src T, name string) {
>>> if *dst != nil { // any can't be compared with nil
>>> panic(fmt.Errorf("too many %s arguments", name))
>>> }
>>> *dst = src
>>> }
>>>
>>> Using this function in each assignment, instead of inlining the
>>> four-line construct with panic, can save a lot of space and make code a lot
>>> more readable.
>>> The above doesn't work, because not every type can be assigned nil.
>>> The following also doesn't work:
>>>
>>> func maybeAssign[T comparable](dst *T, src T, name string) {
>>> var zero T
>>> if *dst != zero { // interface and other nillable types can't be
>>> compared to zero
>>> panic(fmt.Errorf("too many %s arguments", name))
>>> }
>>> *dst = src
>>> }
>>>
>>> Because interface values aren't comparable. (As aren't chans, maps, etc,
>>> but THOSE can be jammed into various interface constructs, whereas "any
>>> interface" cannot, because "interface{}" doesn't actually mean "any
>>> interface")
>>>
>>> Let me try to answer:
>>>
>>> > Why is the *specific* split into (interfaces, pointers, slices,
>>> functions, maps, channels) and (numbers, booleans, strings, structs,
>>> arrays) a particularly important one?
>>>
>>> Because, while go tries very hard to make sure every storable type has a
>>> "zero value," it somehow decides that you can't necessarily COMPARE to that
>>> zero value.
>>> But the whole point of zero values is that you can tell them from
>>> non-zero values!
>>> So, the language has introduced a work-around with the concept of "I can
>>> compare to nil" for these reference types that aren't comparable to their
>>> zero value.
>>> But generics don't allow us to sense or make use of this, so generics
>>> can't express what the regular language can express. Even a very simple
>>> case like the above, can't currently be expressed, and this leads to more
>>> verbose code that's harder to read and harder to work with. (Granted, this
>>> is my opinion, but I'm not alone.)
>>>
>>
>> That does not actually answer the question, though. Again, note that your
>> problem would be solved both by #61372
>>  (you could write `if *dst !=
>> zero`) and by #62487  (you
>> could just write `if *dst != nil`), neither of which require you to make a
>> distinction between "nilable" types and "non-nilable" types. In fact, it
>> would make your `maybeAssign` function worse - it would be less general,
>> because it could only be used with a subset of types and it's not clear why
>> that subset is a good one.
>>
>> (also, nit: channels are comparable)
>>
>> If the language instead changes so that nil means "the zero value" in
>>> general, and it so happens that these nil-comparable types can be compared
>>> to nil without any particular qualification, that also solves the problem.
>>>
>>
>> Right. That is what my question was getting at.
>>
>>
>>> That might indeed be a good solution -- but if so, it'd be nice to know
>>> what we can do to make that happen, and what the other opposition to that
>>> change might be, because that change also feels much less narrow than a
>>> "nil" type constraint.
>>>
>>
>> Being "less narrow" can mean two things: It can mean "it is a more
>> general solution" and it can mean "it is a bigger change". The two
>> proposals above are a similarly big change, that are more general in the
>> kinds of problems they solve. So they seem better.
>>
>>
>>>
>>>
>>> Sincerely,
>>>
>>> Jon Watte
>>>
>>>
>>> --
>>> "I find that the harder I work, the more luck I seem to have." --
>>> Thomas Jefferson
>>>
>>>
>>> On Tue, Oct 3, 2023 at 10:41 PM Axel Wagner <
>>> axel.wagner...@googlemail.com> wrote:
>>>
 Oh (sorry, being forgetful) and re "it's less of a new mechanism than
 introducing a zero identifier": #62487
  introduces *even less* new
 mechanism, by expanding comparison t

[go-nuts] Clace: Secure web application development platform using Starlark

2023-10-18 Thread Ajay Kidave
Hey,

I have been working on a new open source project 
https://github.com/claceio/clace for the past few months. Clace is an 
Apache-2 licensed platform for building secure internal web applications. 
The end goal is to allow fully custom applications as well as workflow type 
applications. Custom apps are supported currently, workflows will come 
later. Clace allows you to build Hypermedia first web applications, where 
the server API returns HTML instead of JSON. With the HTMX[1] library on 
the client side, it makes developing and maintaining interactive websites 
much easier as compared to the regular Javascript SPA model.

Clace is a single binary go application, using sqlite for app metadata. 
Clace apps are written in Starlark [2], which gives a python based syntax. 
The API routes are defined to be Hypermedia first, using the Chi 
library[7]. Each API specifies what HTML to return for a full page reload 
and what to return for a partial request from HTMX. Go HTML templates are 
used for the response. The starlark code runs in a sandbox, it can make 
external calls through plugins. The plugin boundary is used to enforce 
security policies[3]. This allows for policies like permit GET requests but 
not POST/DELETE, which are difficult to do with a container or jail based 
approach.

Clace bundles esbuild to allow importing javascript libraries as ESModules. 
TailwindCSS/DaisyUI watcher integration is supported, although many simple 
apps can use classless CSS libraries. The goal is to have a no build 
approach, the dev artifacts are checked into git and directly used for 
serving prod. Importing new ESM libraries or new TailwindCSS classes 
requires a one time setup operation, which runs automatically in dev mode. 
Other than that, most code changes do not need a build step. Content hash 
based file names with a virtual file system is used, similar to hashfs[4]. 
This allow for aggressive static content caching, even without a build step 
doing file renames. For deployment, certmagic[5] is used for automatic TLS 
certs. App routing is supported based on path and/or domain, allowing for 
deployment flexibility. The plan is to allow plugins to be loaded 
dynamically using go-plugin[6], currently two plugins are built into the 
server, exec for running CLI command and http for REST API calls. Building 
UI for CLI tools and backend for frontend type use-cases are supported 
currently.

https://github.com/claceio/clace/tree/main/examples/ has some simple sample 
apps (the *_gen* files are auto generated), the sample apps are running 
online at https://demo.clace.io/

If you are building Web interfaces with Go HTML templates, I believe Clace 
will make the development process much easier. Do try it out and let me 
know any feedback.

Regards
Ajay

[1]: https://htmx.org/
[2]: https://github.com/google/starlark-go
[3]: https://clace.io/docs/applications/appsecurity/#security-model
[4]: https://github.com/benbjohnson/hashfs
[5]: https://github.com/caddyserver/certmagic
[6]: https://github.com/hashicorp/go-plugin
[7]: https://github.com/go-chi/chi

-- 
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/87dbe1af-32e1-4517-8681-80642789f8dcn%40googlegroups.com.


Re: [go-nuts] shiny, windows, and goroutines

2023-10-18 Thread Nigel Tao
On Wed, Oct 18, 2023 at 9:55 PM SuperTXT Team  wrote:
> I'm experimenting with shiny, trying to develop a wire protocol for
> it. I have some questions about the interfaces.
>
> It seems from some of the examples in the documentation and some
> tutorials that everything except perhaps sending custom window events
> (to trigger updates to the UI) occur on a single event loop goroutine,
> which is the same one that the driver's Main function runs in. This
> isn't spelled out in the screen interfaces, so I wonder if this is
> really a true constraint.
>
> If this is true, then how does one handle multiple active windows? The
> window.NextEvent() is blocking, and isn't a channel that permits
> selecting on multiple windows at once.
>
> Otherwise, if it's expected that in some scenarios, such as multiple
> windows, that there will be more goroutines what sorts of permissible
> goroutine configurations are allowed? Can I have a goroutine per
> window, or can any goroutine access anything at any time?

It's been a long time, so I can't remember all of the details, but I
think you can have goroutine per window. Grepping the
golang.org/x/exp/shiny/driver/*driver code for sync.Mutex gives
multiple hits.

You're right that the docs aren't helpful here. However, we were all
re-assigned from shiny (to working on other things) well before shiny
hit anything close to a "1.0 quality" milestone. And the initial focus
was on the single-window use case. For example, on mobile, you
couldn't even have multiple windows. All of the shiny/example programs
use a single window. I wouldn't be surprised if trying to use multiple
shiny windows doesn't work very well.

-- 
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/CAOeFMNV%2Bx-9fZ-X88rNfT_20_%3D9LCwnhOx0%3DgtSkm9-DXChHzA%40mail.gmail.com.


Re: [go-nuts] Generic "nillable" constraint

2023-10-18 Thread Jon Watte
> The two proposals above are a similarly big change, that are more general
in the kinds of problems they solve. So they seem better.

Well, if that would happen, my complaint would go away, so I'd be happy
with that.

I think "making all values comparable" is a worse change though (there's a
reason they aren't comparable!) and making everything comparable to nil
without type qualification is better IMO.

Sincerely,

Jon Watte


--
"I find that the harder I work, the more luck I seem to have." -- Thomas
Jefferson


On Tue, Oct 17, 2023 at 10:25 PM Axel Wagner 
wrote:

> On Wed, Oct 18, 2023 at 6:09 AM Jon Watte  wrote:
>
>> Circling back to this, because it came up today again.
>>
>> Here's the generic function I want to write. It comes up in a lot of
>> function composition, which in turn comes up in a lot of interface adapters
>> and such:
>>
>> func maybeAssign[T any](dst *T, src T, name string) {
>> if *dst != nil { // any can't be compared with nil
>> panic(fmt.Errorf("too many %s arguments", name))
>> }
>> *dst = src
>> }
>>
>> Using this function in each assignment, instead of inlining the four-line
>> construct with panic, can save a lot of space and make code a lot more
>> readable.
>> The above doesn't work, because not every type can be assigned nil.
>> The following also doesn't work:
>>
>> func maybeAssign[T comparable](dst *T, src T, name string) {
>> var zero T
>> if *dst != zero { // interface and other nillable types can't be
>> compared to zero
>> panic(fmt.Errorf("too many %s arguments", name))
>> }
>> *dst = src
>> }
>>
>> Because interface values aren't comparable. (As aren't chans, maps, etc,
>> but THOSE can be jammed into various interface constructs, whereas "any
>> interface" cannot, because "interface{}" doesn't actually mean "any
>> interface")
>>
>> Let me try to answer:
>>
>> > Why is the *specific* split into (interfaces, pointers, slices,
>> functions, maps, channels) and (numbers, booleans, strings, structs,
>> arrays) a particularly important one?
>>
>> Because, while go tries very hard to make sure every storable type has a
>> "zero value," it somehow decides that you can't necessarily COMPARE to that
>> zero value.
>> But the whole point of zero values is that you can tell them from
>> non-zero values!
>> So, the language has introduced a work-around with the concept of "I can
>> compare to nil" for these reference types that aren't comparable to their
>> zero value.
>> But generics don't allow us to sense or make use of this, so generics
>> can't express what the regular language can express. Even a very simple
>> case like the above, can't currently be expressed, and this leads to more
>> verbose code that's harder to read and harder to work with. (Granted, this
>> is my opinion, but I'm not alone.)
>>
>
> That does not actually answer the question, though. Again, note that your
> problem would be solved both by #61372
>  (you could write `if *dst !=
> zero`) and by #62487  (you
> could just write `if *dst != nil`), neither of which require you to make a
> distinction between "nilable" types and "non-nilable" types. In fact, it
> would make your `maybeAssign` function worse - it would be less general,
> because it could only be used with a subset of types and it's not clear why
> that subset is a good one.
>
> (also, nit: channels are comparable)
>
> If the language instead changes so that nil means "the zero value" in
>> general, and it so happens that these nil-comparable types can be compared
>> to nil without any particular qualification, that also solves the problem.
>>
>
> Right. That is what my question was getting at.
>
>
>> That might indeed be a good solution -- but if so, it'd be nice to know
>> what we can do to make that happen, and what the other opposition to that
>> change might be, because that change also feels much less narrow than a
>> "nil" type constraint.
>>
>
> Being "less narrow" can mean two things: It can mean "it is a more general
> solution" and it can mean "it is a bigger change". The two proposals above
> are a similarly big change, that are more general in the kinds of problems
> they solve. So they seem better.
>
>
>>
>>
>> Sincerely,
>>
>> Jon Watte
>>
>>
>> --
>> "I find that the harder I work, the more luck I seem to have." -- Thomas
>> Jefferson
>>
>>
>> On Tue, Oct 3, 2023 at 10:41 PM Axel Wagner <
>> axel.wagner...@googlemail.com> wrote:
>>
>>> Oh (sorry, being forgetful) and re "it's less of a new mechanism than
>>> introducing a zero identifier": #62487
>>>  introduces *even less* new
>>> mechanism, by expanding comparison to (and assignment of) `nil` to all
>>> types inside a generic function. It's not a new class of constraint, it
>>> just special-cases `nil` a bit more. So it is still a far more general
>>> mechanism, that solves more problems than `nilabl

[go-nuts] shiny, windows, and goroutines

2023-10-18 Thread SuperTXT Team
Hi All,

I'm experimenting with shiny, trying to develop a wire protocol for
it. I have some questions about the interfaces.

It seems from some of the examples in the documentation and some
tutorials that everything except perhaps sending custom window events
(to trigger updates to the UI) occur on a single event loop goroutine,
which is the same one that the driver's Main function runs in. This
isn't spelled out in the screen interfaces, so I wonder if this is
really a true constraint.

If this is true, then how does one handle multiple active windows? The
window.NextEvent() is blocking, and isn't a channel that permits
selecting on multiple windows at once.

Otherwise, if it's expected that in some scenarios, such as multiple
windows, that there will be more goroutines what sorts of permissible
goroutine configurations are allowed? Can I have a goroutine per
window, or can any goroutine access anything at any time?

Thanks!

-- 
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/CAEEr3T7e7%2Bb%3DWivLbOa%2B7uDucNbCAVM6D3mwX-DaUgwRnAvh0A%40mail.gmail.com.