In Which @Captain asks C# Beginner Questions
-
I have to write a file exporter thingie. Right now, I'm formatting the lines to fit the spec, and I'm not sure what it should look like in C#. In Haskell, I'd write code like:
make_line :: [String] -> String make_line fields = ( foldl (\item next -> item ++ "*" ++ next) fields ) ++ "~\n"
Yeah, that's the stupid format. Fields are asterisk
*
delimited, and lines end with a~
and a newline.How do I do that in C#? (I told you it was a beginner question) I guess I'll need a loop and accumulator. What kind of loop should I use?
Be gentle, it's my first time with C#.
-
Assuming I'm parsing the Haskell code correctly:
public string MakeLine( IEnumerable<string> fields ) { return string.Join( "*", fields ) + "~\n"; }
-
@Captain said in In Which @Captain asks C# Beginner Questions:
I have to write a file exporter thingie. Right now, I'm formatting the lines to fit the spec, and I'm not sure what it should look like in C#. In Haskell, I'd write code like:
make_line :: [String] -> String make_line fields = ( foldl (\item next -> item ++ "*" ++ next) fields ) ++ "~\n"
Yeah, that's the stupid format. Fields are asterisk
*
delimited, and lines end with a~
and a newline.How do I do that in C#? (I told you it was a beginner question) I guess I'll need a loop and accumulator. What kind of loop should I use?
Be gentle, it's my first time with C#.
for the parse, assuming you can use LINQ:
string data = ""; //all the data IEnumerable<string[]> fields = from row in data.Split(new [] {"~\n"}, StringSplitOptions.None) select row.Split(new[] { "*" }, StringSplitOptions.None);
-
Cool. Does C# have a nice syntax for declaring lists? All I'm seeing is stuff like:
List<string> list = new List<string>(); list.Add("anchovy"); list.Add("barracuda"); list.Add("bass"); list.Add("viperfish");
which gives me a stomach ache.
-
@Captain said in In Which @Captain asks C# Beginner Questions:
Cool. Does C# have a nice syntax for declaring lists? All I'm seeing is stuff like:
List<string> list = new List<string>(); list.Add("anchovy"); list.Add("barracuda"); list.Add("bass"); list.Add("viperfish");
which gives me a stomach ache.
var list = new List<string> {"anchovy", "barracuda", "bass", "viperfish"};
-
var list = new List<string> { "anchovy", "barracuda", "bass", "viperfish" };
-
This post is deleted!
-
OK, here's a slightly harder one. What's the best way to persist a value between program runs?
We have to "name" our batches with unique batch numbers. So my plan is to read an int from "somewhere" at the start of the program run, use that to populate the various things that need it, and then increment the stored value.
I don't have a database to work with. What's my best option?
-
@accalia He'd probably like
var list = [] {"blah"}
, but that's obviously an array, so maybe not ideal.@Captain said in In Which @Captain asks C# Beginner Questions:
OK, here's a slightly harder one. What's the best way to persist a value between program runs?
We have to "name" our batches with unique batch numbers. So my plan is to read an int from "somewhere" at the start of the program run, use that to populate the various things that need it, and then increment the stored value.
I don't have a database to work with. What's my best option?A database is quite a lot for one field, so you could possibly put it in Settings, possibly in App.config, possibly in your own file, or just generate guids. All pretty easy.
-
I didn't know C# doesn't care about comma-fixity. I like that. A lot.
-
@Captain said in In Which @Captain asks C# Beginner Questions:
What's the best way to persist a value between program runs?
Depends on how far it needs to be persisted. For simple runs on a local machine, use:
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)
That'll give you AppData on Windows and equivalent on other OSes.
So you'd want something like:
var path = Path.Combine( Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "MyApp", "data-file.txt" ); File.WriteAllText( path, fileContents );
(Windows.Forms has
Application.UserAppDataPath
which is that plus automatically fills in your Company Name, Application Name, and version number. But only works on Windows.)If you wanna save an object, .net has a really good XML serializer and a really bad JSON serializer built-in. If you want to do JSON, use Newtonsoft's serializer, it's about 47,000 times easier and faster than the built-in.
If you need to persist the data to other machines on your same network, you can save the file to a network share or a database. If you need to persist to somewhere else in the world, then ... well, figure out what cloud service you're using and we'll go from there.
-
I'm happy with the plain text file solution. JSON is probable. Thanks for the pointers.
-
@Captain said in In Which @Captain asks C# Beginner Questions:
We have to "name" our batches with unique batch numbers.
Does it have to be a sequence number? Why not uses another method which does not require storing a value between runs?
-
@jaming For the record, I'd also use a GUID for this. Each batch can have a unique GUID, you're assured there's no collisions, and you don't need batch X to be dependent on knowing the serial number of X-1 before you kick it off. (A.k.a. you can run batches in parallel if needed.)
-
@jaming, @blakeyrat: I would use a GUID, but the batch number the state is expecting is a 6 digit int. It only has to be unique, but sequences make that easier than any alternative I can think of.
-
@Captain Pfft. Time to move to a new state.
-
6 digits isn't much to shove something stateless in. Could you go timestamp-based? Minutes since some epoch has you covered for 2 years.
-
@blakeyrat said in In Which @Captain asks C# Beginner Questions:
Time to move to a new state.
Our systems still expect Zip Code to be 100% numeric. Where should I go? How should I get there? Is there really a light at the end of the tunnel?
-
@Tsaukpaetra said in In Which @Captain asks C# Beginner Questions:
Is there really a light at the end of the tunnel?
Yes.
You ->
-
@PleegWat this process is going to increment that int once a quarter or so. 250,000 years is good enough.
-
@Captain said in In Which @Captain asks C# Beginner Questions:
I didn't know C# doesn't care about comma-fixity. I like that. A lot.
Can I flip this thread's purpose around for a sec and ask for a short example to demonstrate what you are talking about?
-
@Captain
As an aside, since your questions seem to be answered: if you want to do stuff functionally in .NET, you could try F#. It's supported in VS and cross-compatible with C# (not sure what, if any, limits are on that). Although it's from the OCaml family, so not quite the same as Haskell. I think the equivalent would be something like:let make_line fields = (List.fold (fun acc next -> acc + "*" + next) "" fields) + "~\n"
in F# interactive:
> let f = ["a"; "b"; "c"];; val f : string list = ["a"; "b"; "c"] > let make_line fields = (List.fold (fun acc next -> acc + "*" + next) "" fields) + "~\n";; val make_line : fields:string list -> string > make_line f;; val it : string = "*a*b*c~ " >
As for how to use that with C#, here are the two files in a demo I made:
F# library:
module FSharpToCSharpDemoLibrary.Exports let make_line fields = (Seq.fold (fun acc next -> acc + "*" + next) "" fields) + "~\n"
C# console program:
using System; using System.Collections.Generic; using FSharpToCSharpDemoLibrary; namespace FSharpToCSharpDemo { class Program { static void Main(string[] args) { var list = new List<string> { "anchovy", "barracuda", "bass", "viperfish" }; Console.WriteLine(Exports.make_line(list)); Console.ReadLine(); } } }
TwoThree notes here:- I used
Seq.fold
instead ofList.fold
here becauseList<T>
in C# maps to aSeq
in F#. This is because the F#List
type is immutable, which the C#List<T>
isn't. - Each file is in a different project because I guess you can't put the two different types in the same project? But you can mix them in the same solution.
- The C# client to the F# library has to have references to both the F# library DLL and
FSharp.Core
.
Looks like our highlighter either isn't highlight.js, or for some reason it doesn't like the F# hints, so they've been removed.
Noticed my implementation doesn't quite do what I think you intended, so here's an update:
module FSharpToCSharpDemoLibrary.Exports let make_line fields = match Seq.toList fields with | (x::xs) -> (List.fold (fun acc next -> acc + "*" + next) x xs) + "~\n" | [] -> "~\n"
- I used
-
@Dreikin said in In Which @Captain asks C# Beginner Questions:
fun acc next -> acc + "*" + next
String concatenation via + is nasty though. Unless F# can optimize that fold to a
StringBuilder
, but I don't think so...
-
@Maciejasjmj said in In Which @Captain asks C# Beginner Questions:
@Dreikin said in In Which @Captain asks C# Beginner Questions:
fun acc next -> acc + "*" + next
String concatenation via + is nasty though. Unless F# can optimize that fold to a
StringBuilder
, but I don't think so...I'm not sure, but I wasn't really too concerned with that for the examples - I was mostly trying to show a directly parallel example to what he had written. Looking it up, it appears using
String.concat separator strings
would be correct. I.e.:let make_line fields = String.concat "*" fields + "~\n"
Which, bonus, is both shorter and doesn't have any funky C# -> F# type weirdness.
Also just noticed that I should use
Seq.reduce
instead ofSeq.fold
for the intended result, as far as direct comparisons go:let make_line fields = Seq.reduce (fun acc next -> acc + "*" + next) fields + "~\n"
-
@Captain said in In Which @Captain asks C# Beginner Questions:
It only has to be unique, but sequences make that easier than any alternative I can think of.
I wouldn't be at all surprised if some auditor somewhere thinks that the IDs should be exactly sequential. Or the date.
-
@Maciejasjmj said in In Which @Captain asks C# Beginner Questions:
String concatenation via + is nasty though
It's converted to a String.Concat() in a case like that. IMO it's only a problem when you're doing it in a loop. Declaring a string as
someString + "a constant" + someOtherString
is fine in my personal style guide
-
@blakeyrat said in In Which @Captain asks C# Beginner Questions:
(Windows.Forms has Application.UserAppDataPath which is that plus automatically fills in your Company Name, Application Name, and version number. But only works on Windows.)
Out of interest, any idea why this is a part of forms rather than lower in the stack? Because this schema is completely applicable on Linux and OSX as well AFAIK, so something like Mono should be able to implement it correctly in a cross-platform manner. Seems a bit silly is all.
-
@Jaloopa said in In Which @Captain asks C# Beginner Questions:
IMO it's only a problem when you're doing it in a loop.
But a reduce is a (kind of) loop.
-
@Onyx said in In Which @Captain asks C# Beginner Questions:
Out of interest, any idea why this is a part of forms rather than lower in the stack?
I believe because it's a VB6 compatibility thing. But I'm not 100% sure on that.
-
Couldn't you initialize the accumulator with a stringbuilder instead of a string, or does that not work if you want to not start with a separator?
-
@PleegWat said in In Which @Captain asks C# Beginner Questions:
Couldn't you initialize the accumulator with a stringbuilder instead of a string
Does that even work with the
+
operator? (I know it's used to implement the+
when applied to stringsβ¦)
-
@PleegWat Maybe you should just back up a step and stop optimizing code without measuring it or determining whether optimal performance matters or not.
-
@JBert Fixity just means "position of an operator relative to its arguments". So, typical functional notation uses fixity like
f x
to apply the functionf
tox
. "Comma fixity" is a term I just made up to distinguish between:list = [ theFirst, theSecond, theThird ]
and
list = [ theFirst , theSecond , theThird ]
The point being, C# doesn't care which I type. (I prefer the latter notation)
-
@Captain said in In Which @Captain asks C# Beginner Questions:
(I prefer the latter notation)
-twitch-
but....
-twitch-
that's.....
-twitch-
-
@Captain said in In Which @Captain asks C# Beginner Questions:
The point being, C# doesn't care which I type
As long as there's some whitespace between tokens, C# doesn't give a shit how much or what type it is. A line only ends at a semi colon.
-
@Captain said in In Which @Captain asks C# Beginner Questions:
I didn't know C# doesn't care about comma-fixity. I like that. A lot.
Yeeeees.
Yeeeeeeeees.
You want this ... don't you?
Join us!
One of us! One of us! One of us! :D
-
@accalia don't you ever forget to type a comma and then have to go item by item in a long list until you find which item was missing it? Maybe C# has better error reporting that other languages where I've done that, but I've been burned by that kind of thing too many times.
-
@PleegWat said in In Which @Captain asks C# Beginner Questions:
Couldn't you initialize the accumulator with a stringbuilder instead of a string
Trivial in C#, although the fold functor is not a pure function in this case, and you have to deal with the asterisk at the end.
var myList = new List<string> { "apples", "bananas", "oranges", "idontknowanymorefruits" }; var sb = new StringBuilder(); var sameStringBuilderActually = myList.Aggregate(sb, (x, y) => x.Append(y).Append("*")); var nowWithAString = myList.Aggregate((x, y) => x + "*" + y); Console.WriteLine(sameStringBuilderActually); Console.WriteLine(nowWithAString);
-
@Captain said in In Which @Captain asks C# Beginner Questions:
@JBert Fixity just means "position of an operator relative to its arguments". So, typical functional notation uses fixity like
f x
to apply the functionf
tox
. "Comma fixity" is a term I just made up to distinguish between:list = [ theFirst, theSecond, theThird ]
and
list = [ theFirst , theSecond , theThird ]
The point being, C# doesn't care which I type. (I prefer the latter notation)
I also prefer that format. I picked it up from SQL stuff.
[waves] Hiiiii @accalia
-
@Captain said in In Which @Captain asks C# Beginner Questions:
@accalia don't you ever forget to type a comma and then have to go item by item in a long list until you find which item was missing it?
nah. resharper's got my back on that one. tells me right where it is.
also vs itself will, as will the various lint tools i use for various languages.
-
@accalia said in In Which @Captain asks C# Beginner Questions:
@Captain said in In Which @Captain asks C# Beginner Questions:
@accalia don't you ever forget to type a comma and then have to go item by item in a long list until you find which item was missing it?
nah. resharper's got my back on that one. tells me right where it is.
also vs itself will, as will the various lint tools i use for various languages.
You got resharper on you? Eww. You know that shizz don't wash off, right?
-
@Vaire said in In Which @Captain asks C# Beginner Questions:
You got resharper on you?
i'v also got sharpie on me.
they make great semi-permanent tattoos.
-
@accalia said in In Which @Captain asks C# Beginner Questions:
@Vaire said in In Which @Captain asks C# Beginner Questions:
You got resharper on you?
i'v also got sharpie on me.
they make great semi-permanent tattoos.
I would be willing to ignore your use of resharper in exchange for a pony-tat
-
@Vaire said in In Which @Captain asks C# Beginner Questions:
@accalia said in In Which @Captain asks C# Beginner Questions:
@Vaire said in In Which @Captain asks C# Beginner Questions:
You got resharper on you?
i'v also got sharpie on me.
they make great semi-permanent tattoos.
I would be willing to ignore your use of resharper in exchange for a pony-tat
which pony?
-
@Captain It also doesn't care if you add a trailing comma:
list = [ theFirst, theSecond, theThird, ];
Which is brilliant and every programming language should support it dammit.
-
@Vaire What's wrong with Resharper?
-
@Captain said in In Which @Captain asks C# Beginner Questions:
don't you ever forget to type a comma and then have to go item by item in a long list until you find which item was missing it?
Get an IDE.
-
@accalia said in In Which @Captain asks C# Beginner Questions:
@Vaire said in In Which @Captain asks C# Beginner Questions:
@accalia said in In Which @Captain asks C# Beginner Questions:
@Vaire said in In Which @Captain asks C# Beginner Questions:
You got resharper on you?
i'v also got sharpie on me.
they make great semi-permanent tattoos.
I would be willing to ignore your use of resharper in exchange for a pony-tat
which pony?
Twilight Sparkle, of course!
-
@asdf said in In Which @Captain asks C# Beginner Questions:
@Vaire What's wrong with Resharper?
Nothing, I think it is rather unnecessary in VS 2012+, but mostly I just like poking @accalia
-
@Vaire apparently she gets boned front and back so poking her isn't too hard