|
pointsofdata posted:I don't understand the theory, but my question is: would typeclasses give us discriminated unions in c#? Nope, totally unrelated. DUs are about the shape of data, typeclasses are about what functions exist that operate on that data.
|
# ? Sep 1, 2021 12:15 |
|
|
# ? Jun 1, 2024 20:04 |
|
mystes posted:Someone on Reddit a couple months ago claimed that they didn't want to try to add typeclasses to f# because there was a distinct possibility they were actually going to get added to .net in general. https://github.com/fsharp/fslang-suggestions/issues/243#issuecomment-282480054 Along with other relevant stuff in this years-old comment thread. F# has been burned a number of times by being first-to-implement, even without 'built-in' CLR support - at which point C# comes along later, drags the CLR team with them, and then F# needs to worry about interop/compatibility as well as not breaking backwards compatability for itself. See: Tuples, Async, Records. Along with that - SRTP in F# is already most of the way to doing a lot of typeclass-y stuff, even if the syntax is obtuse to a fault.
|
# ? Sep 4, 2021 15:11 |
|
Cuntpunch posted:https://github.com/fsharp/fslang-suggestions/issues/243#issuecomment-282480054
|
# ? Sep 4, 2021 15:19 |
|
mystes posted:It makes sense not to implement an incompatible version just for f# if it might get added to c# later, but I wish there was a way to get a spec agreed to for both languages even if c# didn't have immediate plans to support it, or something like that. The trouble is that you also end up on different timelines, and also *outlooks* on things. In that blog post mentioned, there's this chain of discussion from a veteran in the F# community: https://devblogs.microsoft.com/dotnet/preview-features-in-net-6-generic-math/#comment-9927 There is, at times, what seems to be a mismatch between outlooks - another great read on where C# jumped the gun and F# kind of suffers from interop concerns is around default interface methods - not even a feature that F# wants to implement. https://github.com/dotnet/csharplang/issues/288#issuecomment-288114545 So taking these two very different languages, paradigms, and outlooks - and then trying to plan on something today that C# may (never?) implement is going to be tricky to get their buy-in on...today.
|
# ? Sep 4, 2021 15:41 |
|
remember that "clr" stands for "c# language runtime"
|
# ? Sep 5, 2021 09:27 |
|
What's the good way of doing platform independent, writable-at-runtime program state/settings? I've built my program around using the app.config/ConfigurationManager, which is a bit clunky with the conversions but it worked until I came across this issue where standalone exes don't work well with it. Literally everyone says app.config is old and crap so I start changing everything over to using appsettings.json/JsonConfigurationProvider and oh - great - turns out that's readonly. It looks like there are workarounds for both systems to make them do what I want, but is there a better way? Maybe a third party nuget configuration package that everyone loves? I've been using the C# 8 in a nutshell book which has been brilliant for steering me away from obsolete patterns i've picked up from stackoverflow, but it says nothing about configuration storage.
|
# ? Sep 5, 2021 22:49 |
|
I just went through this! The Configuration system in Core (and above) is a hierarchical, multi-layered providers-based approach. All configuration key/values are ultimately turned into a colon-separated key, with a value. So, the following JSON becomes: code:
So, if you have multiple sources, what gets updated on Save?
|
# ? Sep 6, 2021 00:09 |
|
Ireland Sucks posted:What's the good way of doing platform independent, writable-at-runtime program state/settings? For Containers I use the Environment stuff. For my own little projects I just create a small object that holds my configuration data, set some sane defaults, and I serialize this to disk as a JSON file, next time the program runs I deserialize it from disk. It is pretty simple but works pretty much every time. Edit: Added bonus: if NewtonSoft can deserialize/serialize it, you can pretty much use anything you want in the file and it is pretty easy to use a text editor to add data without needing to recompile. It might not be "the" way but I find it works well. Mr Shiny Pants fucked around with this message at 08:00 on Sep 6, 2021 |
# ? Sep 6, 2021 07:52 |
|
If it's writable at runtime it's not really 'application configuration' in the way that most developers use the term, and if you go looking for that you'll get unhelpful results (like appsettings.json, environment variables, CLI arguments etc... all of which are read-only and/or ephemeral, on purpose). If it's writable at runtime it's application state, and it's also user data, so you want to search for 'how do I persist a small amount of data'. The answer is likely to be a simple JSON file (overwrite/reload on save) or, once the data grows enough, a SQLite database. And you want to save them in a user-owned folder if different users on the same machine are supposed to be able to have their own configuration each.
|
# ? Sep 6, 2021 10:42 |
|
Thanks, yeah - it looks like JSON deserialisers are good enough to make this relatively painless so I'll do something custom.
|
# ? Sep 6, 2021 15:55 |
|
I have an Order class with a list of a bunch of specific Items. Some of these items are mandatory, some are limited 1 one, and some have no limit, and we have a concrete subclass for each of these items. How would you enforce these rules in code? One of my coworkers suggested adding an enum to each class, but I don't like mixing object data with class data like that.
|
# ? Sep 12, 2021 13:56 |
|
Boz0r posted:I have an Order class with a list of a bunch of specific Items. Some of these items are mandatory, some are limited 1 one, and some have no limit, and we have a concrete subclass for each of these items. How would you enforce these rules in code? Not sure I really understand what you're describing. Your Order class has a property which is a List<OrderItem>? Are the types of OrderItem that exist fixed (changing it requires a new version of the software), or do users of the system have to be able to add more? You could make OrderItem an abstract class and require concrete subclasses to have a ValidateOrder() method which validates a list of OrderItems, I guess. Then you can validate an Order's list of OrderItems by iterating over the list and calling ValidateOrder() on each item. That doesn't help you with mandatory items (i.e. the list is invalid if it doesn't contain any items of type X). You could handle that by adding another validation step which checks for the absence of required items. Or instead of iterating over the items, you could iterate over the types of items that exist and validate one type at a time. The types of item that exist might be stored in a database, or it might be stored in a list that is automatically populated using reflection, or it might be hardcoded (in which case you would have to remember to update the hardcoded list whenever you add a new one, which is a potential source of bugs). What do you mean by "add an enum to each class"? What does this putative enum type represent, what are its members? What do you mean when you say "mixing object data with class data"? You mean you don't like objects having properties that are supposed to depend only on the class, i.e. are the same for each object belonging to a specific class? You need to explain your constraints a bit better
|
# ? Sep 12, 2021 14:14 |
|
It seems like it might be easier to do this without a new class for each item type by just having a single class (possibly with the actual item type as a type parameter) that you instantiate once for each item type and configure with the minimum/maximum number allowed and other validation requirements and then either call a factory method that returns an actual container instance or you just call a method to validate a list of the actual item type.
|
# ? Sep 12, 2021 14:35 |
|
Enforcing the "at most one" requirement is easy enough - just have a UniqueItem subclass and a NonUniqueItem subclass. Your Order class will have a HashSet<UniqueItem> (with the comparison key being the product ID or some such) and a regular List<NonUniqueItem>, plus a read-only property exposing an IEnumerable<Item> consisting of the union of the two properties. The "at least one" requirement is more complicated, because how do you guarantee that you know all the MandatoryItem instances that exist? What should happen if somebody creates a new one while you're creating the Order? Without more context, I would pass the list of currently-defined MandatoryItems to the constructor of the OrderFactory class. Then every Order created via OrderFactory.Create() will already contain one of each mandatory item, by default and without the option to remove them. Whenever somebody flags or unflags a product as mandatory, update or replace the OrderFactory.
|
# ? Sep 12, 2021 15:36 |
|
Boz0r posted:I have an Order class with a list of a bunch of specific Items. Some of these items are mandatory, some are limited 1 one, and some have no limit, and we have a concrete subclass for each of these items. How would you enforce these rules in code? As a starting point, I'd simply maintain an enumerable consisting of a bunch of Predicate<Order> lambdas. When the time comes to validate an order, run it through all of the predicates to ensure all return true. Have a rule that says "No more than 3 Widgets"? That's cool: code:
To expand on this thought process: Mixing it into the types around products and orders themselves seems awkward and misplaced abstraction. A product exists in the world without any context that it is part of an order. an order exists as a tally of things. It already mostly makes sense to combine these together via a third thing: a LineItem - such that a raw product(id, manufacturer, price, etc) and order-specific details about it (quantity) can be composed. Trying to encode rules into line items (either via a predicate approach as above, or via subclasses) seems generally more awkward, because it isolates the concept of validity of an order solely to its lineitems, and not to other (plausibly) useful data that's already associated to the order as well - consider that there's no good way in this approach to encode "You can have one or the other, but not both of these on an order" or other outside-the-context-of-a-single-line-item rules: and that goes for trying to do something with Predicate<LineItem> as well. Cuntpunch fucked around with this message at 21:21 on Sep 12, 2021 |
# ? Sep 12, 2021 21:12 |
|
I feel like I'm missing something simple here, but not sure what. I'm trying to use an online service to convert HTML to PDF, and then return a base64 encoded string of the pdf. I can make the call fine, but when I put the returned base64 string into a decoder, I'm only getting like the first 20% of the pdf, the rest is blank. Using Postman and hitting the HtmlToPdf api directly returns the full pdf. Looking at the base64 string, there's a section of "AAAAAAAAAA......etc" in there, so obviously something is going wrong in the encoding. I suspect it's that I'm encoding the entire response and not just the .pdf part, but I'm not sure, or how to get just that part. Here's the code for the call:code:
|
# ? Sep 14, 2021 15:14 |
|
Just-In-Timeberlake posted:I feel like I'm missing something simple here, but not sure what. I'm trying to use an online service to convert HTML to PDF, and then return a base64 encoded string of the pdf. I can make the call fine, but when I put the returned base64 string into a decoder, I'm only getting like the first 20% of the pdf, the rest is blank. Using Postman and hitting the HtmlToPdf api directly returns the full pdf. Looking at the base64 string, there's a section of "AAAAAAAAAA......etc" in there, so obviously something is going wrong in the encoding. I suspect it's that I'm encoding the entire response and not just the .pdf part, but I'm not sure, or how to get just that part. Here's the code for the call: Think you're missing a ReadToEnd()...
|
# ? Sep 14, 2021 15:39 |
|
I rewrote it using HttpClient and it works now, go figurecode:
|
# ? Sep 14, 2021 18:41 |
|
It might be an issue with gzip compression. Some of the older stuff doesn't handle that automatically by default.
|
# ? Sep 14, 2021 19:27 |
|
mystes posted:It might be an issue with gzip compression. Some of the older stuff doesn't handle that automatically by default. This is probably it. You will need to run it trough a stream that can read a ZIP stream. Missing a Flush() at the end of copying it to a memorystream.
|
# ? Sep 15, 2021 05:59 |
|
Does anyone know of a good way to call JavaScript from .NET Core? Specifically, I'd like my ASP.NET service to call a function in an npm package and run it on the back-end. I'm trying to get it work using INodeServices, but it seems that this requires the JavaScript function to have a callback function as an argument. However, this JavaScript that I'm trying to use does not take a callback – it only returns a Promise. I could ask the developers of the npm to add a function that takes that callback, but could I solve it on my service without bothering them? Also, my ASP.NET service is only an API and doesn't have any HTML so I've avoided Blazor, but if that's the best way to get this working then I'd be fine with giving it a go. I'm also now trying the SpaServices extensions that the MS page is talking about, but it seems to not really have any documentation at all. Quite a bizarre situation.
|
# ? Sep 15, 2021 11:22 |
|
Dehumanize yourself and face to writing a trivial, internal-only express.js microservice that exposes the npm functions you want as HTTP endpoints.
|
# ? Sep 15, 2021 12:51 |
|
Dog on Fire posted:Does anyone know of a good way to call JavaScript from .NET Core? Specifically, I'd like my ASP.NET service to call a function in an npm package and run it on the back-end.
|
# ? Sep 15, 2021 13:08 |
|
mystes posted:Can't you just write a trivial javascript wrapper function? Also if INodeServices doesn't work for some reason I guess you could just run it as a process and get the result via stdout? I don't know why I didn't think of the JS wrapper function, thanks!
|
# ? Sep 15, 2021 13:58 |
|
Just-In-Timeberlake posted:I rewrote it using HttpClient and it works now, go figure IIRC, HttpClient is intended to be used as a singleton.
|
# ? Sep 16, 2021 03:27 |
|
Nth Doctor posted:IIRC, HttpClient is intended to be used as a singleton. Not necessarily a singleton, but not disposed with each use, either.
|
# ? Sep 16, 2021 04:03 |
|
Toast Museum posted:Not necessarily a singleton, but not disposed with each use, either. And if one of these errors out, it will take all your other outstanding requests with it if I am not mistaken. Or did they fix that?
|
# ? Sep 16, 2021 05:59 |
|
I think you're meant to use HttpClientFactory now https://docs.microsoft.com/en-us/do...t-http-requests
|
# ? Sep 16, 2021 07:13 |
|
Mr Shiny Pants posted:And if one of these errors out, it will take all your other outstanding requests with it if I am not mistaken. Or did they fix that? If you don't pass a different cancellation token in for every request/endpoint, then a timeout (specifically a timeout, which shows up as a TaskCanceledException) will cancel and raise the exception for every pending request. This is just because they use one cancellation token per instance if you don't pass it in, and it's initialised at instantiation. I believe the 'instance' is the underlying handler rather than the HttpClient class, so you'd have one per endpoint which acts as basically a connection pool for that endpoint. So if your HTTP client does requests to two completely hosts, the two shouldn't be interfering with each other. Either way, HttpClientFactory is the way forwards and it's a lot easier to use. I don't know if named clients are the best way vs just calling the factory to get a generic one, but named clients are the only easy way I'm aware of to set up default headers and things only in one place. Its only downside is that it's tied to the DI framework and not actually generic, but so long as you're using the standard generic/web host it should be OK. If you're migrating a legacy app across that can't use those hosts, you're basically going to have to reimplement it in whatever DI framework you're using.
|
# ? Sep 16, 2021 07:32 |
|
Glad they didn't waste too much time making the esoteric thing of "web requests" too easy.
|
# ? Sep 16, 2021 14:27 |
|
Thanks for the heads up on all that.insta posted:Glad they didn't waste too much time making the esoteric thing of "web requests" too easy. for real, there's like 20 different ways to do the same thing.
|
# ? Sep 16, 2021 14:47 |
|
Red Mike posted:If you don't pass a different cancellation token in for every request/endpoint, then a timeout (specifically a timeout, which shows up as a TaskCanceledException) will cancel and raise the exception for every pending request. This is just because they use one cancellation token per instance if you don't pass it in, and it's initialised at instantiation. I believe the 'instance' is the underlying handler rather than the HttpClient class, so you'd have one per endpoint which acts as basically a connection pool for that endpoint. So if your HTTP client does requests to two completely hosts, the two shouldn't be interfering with each other. So were back to copying Java again with the factory stuff? Oh man. I like my WebRequest to be honest, it is simple and works and every time.
|
# ? Sep 16, 2021 14:50 |
|
If your not using the factory (or not using it properly) you can run into socket exhaustion.
|
# ? Sep 16, 2021 17:08 |
|
Red Mike posted:Either way, HttpClientFactory is the way forwards and it's a lot easier to use. I don't know if named clients are the best way vs just calling the factory to get a generic one, but named clients are the only easy way I'm aware of to set up default headers and things only in one place. The infuriating stuff is that they could very easily havemade the default implementation of HttpClientFactory public and you'd just be able to new it up in e.g. a basic console app or even a powershell script, but instead it's declared internal so you have to go through some pointless DI poo poo just to get access to a factory that retains/disposes the underlying HttpMessageHandlers in an efficient way. Since the default impl, linked above, is 385 lines including whitespace, braces, and comments, and hasn't had functional changes for at least three years, I urge everybody who doesn't need 50MB of DI code to either rip off the code directly, or use the nuget package that did exactly that
|
# ? Sep 16, 2021 17:39 |
|
Dog on Fire posted:Does anyone know of a good way to call JavaScript from .NET Core? Specifically, I'd like my ASP.NET service to call a function in an npm package and run it on the back-end. I know you've got a workable solution but there's also https://github.com/sebastienros/jint
|
# ? Sep 16, 2021 19:12 |
|
Toast Museum posted:Not necessarily a singleton, but not disposed with each use, either. Umm so am i doing this wrong: C# code:
|
# ? Sep 17, 2021 00:03 |
|
LongSack posted:Umm so am i doing this wrong: according to everything I read today to make the switch to HttpClientFactory, this will eventually bite you in the rear end, with the bonus knowing that going by the documentation, you're doing the right thing.
|
# ? Sep 17, 2021 00:07 |
|
LongSack posted:Umm so am i doing this wrong: Yeah. This is one of the exceptions to the rule that you should always dispose of anything that implements IDisposable
|
# ? Sep 17, 2021 01:56 |
|
NihilCredo posted:The infuriating stuff is that they could very easily havemade the default implementation of HttpClientFactory public and you'd just be able to new it up in e.g. a basic console app or even a powershell script, but instead it's declared internal so you have to go through some pointless DI poo poo just to get access to a factory that retains/disposes the underlying HttpMessageHandlers in an efficient way. Nice, the part that gets me: Who thought it would be a good idea in the first place? Why?
|
# ? Sep 17, 2021 06:51 |
|
|
# ? Jun 1, 2024 20:04 |
|
Mr Shiny Pants posted:So were back to copying Java again with the factory stuff? Oh man. I like my WebRequest to be honest, it is simple and works and every time. Classic hot /r/programmerhumor take. Calidus posted:If your not using the factory (or not using it properly) you can run into socket exhaustion. This is the tricky bit of nuance around HttpClient and the awful API design that is still around for backwards compat: The vast majority of people using it will have no problem doing the by-the-book "create a new HttpClient for each request" nonsense. A significant majority will sidestep any potential issues by simply doing something like holding one at class scope for each class that needs to make requests, even if that means having a bunch active at once. The socket-exhaustion/disposable pain comes from use cases involving a significant number of requests and doing so in the 'horrible' using-block way. Everyone curious should grab a spare laptop and intentionally try to trigger some of the deleterious behavior, it's educational in a way that all-caps headlines on Medium about 10 Reasons Why You Are Using HttpClient Wrong struggle to be.
|
# ? Sep 17, 2021 07:33 |