Comments (11)
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.
from saturn.
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.
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.
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.
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.
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.
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.
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.
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.
from saturn.
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.
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)
- Get WebHostEnvironment from CE extension HOT 1
- use_grpc fails if service has multiple constructors
- [Security] Workflow benchmark.yml is using vulnerable action actions/checkout HOT 1
- [Security] Workflow build.yml is using vulnerable action actions/checkout HOT 1
- [Security] Workflow publish.yml is using vulnerable action actions/checkout HOT 1
- [Security] Workflow publish.yml is using vulnerable action mindsers/changelog-reader-action
- Endpoint Routing Still Experimental? HOT 1
- Map Standard Controller to Router or Controller?
- Endpoint router does not have concept of NotFoundHandler HOT 1
- Router executes all getf functions regardless of them being called (in debug only), is passing null into the arguments HOT 2
- Considering file-based router ?
- How To Start a Saturn Project HOT 27
- How to externalize configuration information HOT 2
- requireHeader Pipeline Helper Returning Http 404
- svg has mimetype text/plain
- [MINOR] spelling error in comments in sample application HOT 1
- Update docs to reflect latest changes and use enpoints routing as default?
- Publish Application.fs independent CE for Aspnetcore builder as a separate nuget package with only aspnet dependencies
- Zookeeper zxid溢出后选举.saturn web会出现重连失败.
- sample/ChannelsSample throws error on join HOT 3
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from saturn.