Giter Site home page Giter Site logo

Comments (11)

Krzysztof-Cieslak avatar Krzysztof-Cieslak commented on May 16, 2024 1

TBF, I kinda lean toward keeping CEs, because I don't feel that list provides enough advantages in this case and can get a bit noisier (especially when you start using yields and want to put things in modules for "limiting" access, as Tomas has shown in the last example). But I'll keep the issue open, happy to hear more opinions about it.

CC: @forki @alfonsogarciacaro

from saturn.

baronfel avatar baronfel commented on May 16, 2024 1

A CE is a computation expression, a bounded context where some alternative syntax constructs become available. The official docs for this feature are https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/computation-expressions, and there's a really good series that covers them in depth at https://fsharpforfunandprofit.com/series/computation-expressions.html

from saturn.

isaacabraham avatar isaacabraham commented on May 16, 2024

One thing I like about the CE here is that it goes hand in hand with the other two CEs in Saturn. It might be a little inconsistent to have two "core components" that were CEs but then another one that was just a list.

from saturn.

Krzysztof-Cieslak avatar Krzysztof-Cieslak commented on May 16, 2024

Well, I guess Tomas meant all CEs we use, not only this particular one.

So the main reason is... that I always wanted to do library exposing its API as CE based DSL ;-)

From the implementation point of view - I think managing internal state of those "components" is easier with CE than it would be with list-based solutions, especially for CEs with a rather complex state like application.

From consumer point of view - I like that thanks to using custom keywords all those helper functions (like get or use_gzip etc) are visible and usable only in the scope of given CE - you just can't use them in another place, and editors won't provide those functions in IntelliSense outside of CE.

from saturn.

tpetricek avatar tpetricek commented on May 16, 2024

Yes, @Krzysztof-Cieslak is right - I was thinking of all CEs.

Based on a quick look, the CEs here are just doing some form of function composition - basically a pipeline - so I think technically there is not much difference between the two solutions.

I think the developer experience is the key thing - maybe building the whole framework on top of a couple of CEs defines a unique style that people will learn and like!

I wonder if the fact that you cannot use the CE operations outside of a CE easily breaks how you can compose things. For example, with lists you can do:

let helper = [
  get "/abc" abc
  get "/def" def ]
let oneMain = scope [
  yield get "/" oneHome
  yield! helper ]
let twoMain = scope [
  yield get "/" twoHome
  yield! helper ]

Is there a way to express this with CEs? I guess forward is doing something similar, but not quite?

The auto-complete question is an interesting one too - having the operations only inside the scope of a CE is definitely nice, but I think they are still tricky to discover. In big VS, when you type Ctrl+Space inside CE, you see all top-level definitions and those operations, so finding the CE operations is hard. (Maybe Ionide can do better?)

You could follow the standard List example and do something like:

let topRouter = scope [
    Scope.get "/" helloWorld
    Scope.getf "/name/%s" helloWorldName
    Scope.forward "/other" (scope [
       Scope.error_handler (text "Other 404")
       Scope.get "/" otherHelloWorld
    ])
]

This would be easier to construct (with autocomplete) but it looks uglier - even if Scope. was just S. - so this also is not a silver bullet. Anyway, I think a project like this needs an opinionated main contributor who decides how things should be, and I don't think any solution is perfect :-)

from saturn.

alfonsogarciacaro avatar alfonsogarciacaro commented on May 16, 2024

I don't have a strong opinion, I'd have to use Saturn more to get a better feeling of how CEs fit this case. On one hand, CEs are one of the design features of Saturn and it's reasonable to keep them until the decision is proven right or wrong 😉 On the other hand, I'm sometimes wary of imaginative solutions when there's a simpler one (e.g. I still don't understand the benefit of the middleware simulation in Giraffe instead of just using function composition).

BTW, I would take something different than a router to compare both approaches. For routing, I'd actually like to see something like Giraffe's TokenRouter which speeds up path parsing and matching.

So the advantage of lists is they would make it easier to compose commands. If I'm not wrong the benefit of CEs is they allow to hide a context that is passed through the bindings. IIRC Freya used CEs to create state machines, not sure how this could be applied to Saturn (or whether already is). Another benefit may be the following: when composing functions a là Suave, it is sometimes difficult to know what it's being computed lazily and what eagerly (only once when the app starts), using CEs that may be clearer.

Also, Saturn could drive new uses of CEs the same way as Fable is doing with other F# language features.

from saturn.

isaacabraham avatar isaacabraham commented on May 16, 2024

The context could still be hidden I think - the list itself would just contain the commands; the context / state would be threaded through later in some form of reduce / fold I imagine.

Having tried it out yesterday briefly to port a Giraffe app, the code reducing and simplification is great. However, not being able to "dot into" something to get a list of supported commands within a specific CE is not great - I had to look at an existing example to see what was available. I'd rather have wanted to have been able to figure this out directly in Code.

from saturn.

isaacabraham avatar isaacabraham commented on May 16, 2024

The biggest drawback to custom keywords in CEs is their lack of discoverability. I think that it's still something that should be addressed. The only way I can realistically think of it is to a /// docs to the associated function in the builder e.g.

memory_cache has an associated function, application.MemoryCache. If this was given documentation such as: "Turns on in-memory caching for Saturn. Use the memory_cache keyword to turn this on." it could help. The only alternative is to direct people to the docs site to see what the capabilities are, which isn't great IMHO.

What do you think?

from saturn.

isaacabraham avatar isaacabraham commented on May 16, 2024

Another thing I'm noticing is error reporting e.g. if you enter getF instead of getf, instead of getting a nice compiler error pointing you to getf, you just get an obscure error saying that this the Builder is missing a For method. Even worse, the error shows in the previous route.

image

from saturn.

Krzysztof-Cieslak avatar Krzysztof-Cieslak commented on May 16, 2024

The discoverability problem will be hopefully fixed on tooling level - dotnet/fsharp#4831

The error reporting problem also is a problem of compiler/tooling. I hope, we may try to drive forward fixing those CE issues with Saturn.

from saturn.

drhumlen avatar drhumlen commented on May 16, 2024

I'm new to F# (but I've been programming in Scala for ~5 years). F# is a promising language, but I'm very confused by the syntax in Saturn. What exactly happens inside these bracket? Are get "/" ..... calls to a method with the side-effect of appending to a list? (if so, that doesn't sound very composable/FP). ...Or what's going on here?

Also what is "CE"? I've been googling around and I can't find a definition of "CE".

from saturn.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.