Coding: Fleeting Thoughts

A place to discuss the implementation and style of computer programs.

Moderators: phlip, Moderators General, Prelates

User avatar
Thesh
Made to Fuck Dinosaurs
Posts: 5442
Joined: Tue Jan 12, 2010 1:55 am UTC
Location: Colorado

Re: Coding: Fleeting Thoughts

Postby Thesh » Sun May 21, 2017 11:30 pm UTC

I find the switch to be much cleaner, but I was just showing that you could still do that stuff in C#. I'm in favor of explicit break/continue in switches, personally.
Honesty replaced by greed, they gave us the reason to fight and bleed
They try to torch our faith and hope, spit at our presence and detest our goals

Tub
Posts: 300
Joined: Wed Jul 27, 2011 3:13 pm UTC

Re: Coding: Fleeting Thoughts

Postby Tub » Mon May 22, 2017 10:01 am UTC

speising wrote:Hm. ok, i didn't know about the goto case, but the break seems still unnecessary.

Code: Select all

            case Colors.Green:
            case Colors.Blue:
               Console.WriteLine("Primary");
               break;

Code: Select all

            case Colors.Green:
               break;
            case Colors.Blue:
               Console.WriteLine("Primary");
               break;

There is a difference.

ucim wrote:if ($color == 'red')
{ echo "RED!!!\n";
}

I know that opinions about brace placement differ, but I've never seen this one...

speising
Posts: 2047
Joined: Mon Sep 03, 2012 4:54 pm UTC
Location: wien

Re: Coding: Fleeting Thoughts

Postby speising » Mon May 22, 2017 12:49 pm UTC

Tub wrote:There is a difference.

sure, but since fall-through is only allowed for empty cases, why do we need to spell the break out in non-empty cases?

User avatar
ucim
Posts: 5507
Joined: Fri Sep 28, 2012 3:23 pm UTC
Location: The One True Thread

Re: Coding: Fleeting Thoughts

Postby ucim » Mon May 22, 2017 1:36 pm UTC

Tub wrote:I know that opinions about brace placement differ, but I've never seen this one...
It's the One True Style. Lines up the braces, but collapses the (useless) empty initial line. Interestingly, I do not use this method with arrays that I need to stack.

Jose
Order of the Sillies, Honoris Causam - bestowed by charlie_grumbles on NP 859 * OTTscar winner: Wordsmith - bestowed by yappobiscuts and the OTT on NP 1832 * Ecclesiastical Calendar of the Order of the Holy Contradiction * Please help addams if you can. She needs all of us.

Tub
Posts: 300
Joined: Wed Jul 27, 2011 3:13 pm UTC

Re: Coding: Fleeting Thoughts

Postby Tub » Tue May 23, 2017 8:19 am UTC

speising wrote:sure, but since fall-through is only allowed for empty cases, why do we need to spell the break out in non-empty cases?

Consistency of course. If no break means "fallthrough" on empty cases but "break" on non-empty cases, how many people would be struck by inexplicable and difficult to debug bugs?
The whole point of C# (over C++) is to appeal to people who don't want to sweat the details. That means not having inverted keyword semantics based on the presence of code.

ucim wrote:It's the One True Style. Lines up the braces, but collapses the (useless) empty initial line. Interestingly, I do not use this method with arrays that I need to stack.

Well, it obfuscates indentation, and I personally value clear indentation over matches braces.

I used to defend Allman to the death, until it was pointed out that

Code: Select all

return {
  foo: 42
};

and

Code: Select all

return
{
  foo: 42
};

are not identical in javascript. Can you figure out the difference without googling?

User avatar
Xenomortis
Not actually a special flower.
Posts: 1394
Joined: Thu Oct 11, 2012 8:47 am UTC

Re: Coding: Fleeting Thoughts

Postby Xenomortis » Tue May 23, 2017 9:10 am UTC

That's just because Javascript is the work of Satan.
Image

Demki
Posts: 193
Joined: Fri Nov 30, 2012 9:29 pm UTC

Re: Coding: Fleeting Thoughts

Postby Demki » Tue May 23, 2017 9:55 am UTC

I don't know much javascript but I am guessing line breaks act as statement separators(like semicolon), so the first one acts like

Code: Select all

return;

essentially returning nothing, while the second one has an opening brace so it returns everything until the closing brace.

I am guessing that's because javascript is read line by line, or just bad design.

User avatar
phlip
Restorer of Worlds
Posts: 7542
Joined: Sat Sep 23, 2006 3:56 am UTC
Location: Australia
Contact:

Re: Coding: Fleeting Thoughts

Postby phlip » Tue May 23, 2017 11:01 am UTC

Even better. As you guessed, Javascript will automatically add a semicolon at the end of a line if it makes syntactic sense. But then the brace becomes the start of a block statement, not the start of an object literal. Inside that block is the (useless) label "foo", on the (pointless) statement "42".

Not that it matters, either way it's just dead code after the return. But I like that it still parses fine even though it means something completely different.

Code: Select all

enum ಠ_ಠ {°□°╰=1, °Д°╰, ಠ益ಠ╰};
void ┻━┻︵​╰(ಠ_ಠ ⚠) {exit((int)⚠);}
[he/him/his]

Demki
Posts: 193
Joined: Fri Nov 30, 2012 9:29 pm UTC

Re: Coding: Fleeting Thoughts

Postby Demki » Tue May 23, 2017 11:37 am UTC

phlip wrote:Even better. As you guessed, Javascript will automatically add a semicolon at the end of a line if it makes syntactic sense. But then the brace becomes the start of a block statement, not the start of an object literal. Inside that block is the (useless) label "foo", on the (pointless) statement "42".

Not that it matters, either way it's just dead code after the return. But I like that it still parses fine even though it means something completely different.

That's... horrible. I hope modern Javascript editors warn you about that, I'd much rather get a syntax error than to have code parsed that way.

Edit: Just tried with Visual Studio Code, and indeed it warns you about "unreachable code", underlining the Foo label.

User avatar
Xenomortis
Not actually a special flower.
Posts: 1394
Joined: Thu Oct 11, 2012 8:47 am UTC

Re: Coding: Fleeting Thoughts

Postby Xenomortis » Tue May 23, 2017 11:52 am UTC

Demki wrote:I don't know much javascript but I am guessing line breaks act as statement separators(like semicolon), so the first one acts like

Code: Select all

return;

essentially returning nothing, while the second one has an opening brace so it returns everything until the closing brace.

I am guessing that's because javascript is read line by line, or just bad design.

There are rules as to when Javascript is allowed to insert semicolons.
If it what it's reading doesn't make syntactic sense, but it would with some semicolons (after a line break, "}", or ")"), then it'll add them and try again (unless the ; would result in an empty statement, or is in the the for(...) bit of a for loop, or when there are 9 confirmed planets in the Solar System).
But also a semicolon is inserted if there's a line break after some statements, including the return statement - such statements are not allowed to have a line break before the expression (because return (undefined) is allowed).

Demki wrote:That's... horrible. I hope modern Javascript editors warn you about that, I'd much rather get a syntax error than to have code parsed that way.

Read up on the "defensive semicolon"
Or just read this: https://www.usenix.org/system/files/140 ... ickens.pdf
And watch this: https://www.youtube.com/watch?v=D5xh0ZIEUOE
And weep.
Image

User avatar
ucim
Posts: 5507
Joined: Fri Sep 28, 2012 3:23 pm UTC
Location: The One True Thread

Re: Coding: Fleeting Thoughts

Postby ucim » Tue May 23, 2017 1:35 pm UTC

Tub wrote:I personally value clear indentation over matches braces.
Why? (Serious question.) Matching braces (vertically) makes it easy to identify blocks, and visually the indentation is still clear. Yes, it's annoying that my editor (gedit) won't ignore the opening { when auto-indenting; I could fix that but it's more trouble than it's worth.

If you have a different issue with "matches braces", what is it? Enquiring minds want to know!

Jose
Order of the Sillies, Honoris Causam - bestowed by charlie_grumbles on NP 859 * OTTscar winner: Wordsmith - bestowed by yappobiscuts and the OTT on NP 1832 * Ecclesiastical Calendar of the Order of the Holy Contradiction * Please help addams if you can. She needs all of us.

User avatar
Yakk
Poster with most posts but no title.
Posts: 11045
Joined: Sat Jan 27, 2007 7:27 pm UTC
Location: E pur si muove

Re: Coding: Fleeting Thoughts

Postby Yakk » Tue May 23, 2017 1:44 pm UTC

Braces line up quite clearly with non-brace characters. Detecting brace errors is a very, very small part of a job of a programmer. Warping your coding style to focus on dealing with brace errors is like optimizing your driving to even the wear between turning left and right on your tires.
One of the painful things about our time is that those who feel certainty are stupid, and those with any imagination and understanding are filled with doubt and indecision - BR

Last edited by JHVH on Fri Oct 23, 4004 BCE 6:17 pm, edited 6 times in total.

EvanED
Posts: 4324
Joined: Mon Aug 07, 2006 6:28 am UTC
Location: Madison, WI
Contact:

Re: Coding: Fleeting Thoughts

Postby EvanED » Tue May 23, 2017 2:36 pm UTC

Demki wrote:I hope modern Javascript editors warn you about that, I'd much rather get a syntax error than to have code parsed that way.
My impression as an outsider to webdev is that jslint is both very popular and requires a semicolon after "every" statement. (There are exceptions, like loops and conditionals, where you wouldn't put a ; in C either.)

Yakk wrote:Braces line up quite clearly with non-brace characters. Detecting brace errors is a very, very small part of a job of a programmer. Warping your coding style to focus on dealing with brace errors is like optimizing your driving to even the wear between turning left and right on your tires.
Yeah, I agree with all of this. Like I occasionally have to scroll around a bit to see what lines up with what, but not in situations where braces on separate lines would help.

For all the attention that this issue gets, I'm actually not sure if I've ever introduced a bug that is due to incorrect braces/indentation. Between good editors' electric indent and GCC 6's -Wmisleading-indentation basically makes the whole thing a solved problem IMO, at least for GCC-compatible code that complies cleanly at -Wall.

ucim wrote:Yes, it's annoying that my editor (gedit) won't ignore the opening { when auto-indenting; I could fix that but it's more trouble than it's worth.
I would consider the fact that even you have been too lazy to set up your editor for your indentation style is prima facie evidence that either it's a bad style or you're using an awful editor. At least for me, automatic indentation finds and prevents far more errors than adherence to any particular style would. At this point, with a couple minor exceptions, I really don't care what your style says about braces. Want to put the { on a newline? OK. Same line as previous? OK. Want to require braces around single-statement bodies? OK. Want to omit them? OK. The one thing I kind of care about is if you are using 4-space indents and have a for loop header (or, less commonly, other loops or if) that's multiple lines, I do want the opening brace on a separate line or the body blends into the header.

But a style that precludes automatic indentation -- or makes it "more trouble than it's worth" to set up -- is a style that I think isn't worth considering.

Tub
Posts: 300
Joined: Wed Jul 27, 2011 3:13 pm UTC

Re: Coding: Fleeting Thoughts

Postby Tub » Tue May 23, 2017 3:54 pm UTC

So now we have a couple of opinions saying that javascript is stupid for silently inserting a semicolon when it appears that the user wanted one; and we also have an opinion saying that C# is stupid for NOT silently inserting a break when it appears that the user wanted one.

ucim wrote:
Tub wrote:I personally value clear indentation over matches braces.
Why? (Serious question.)

Because when I want to get a glimpse of block structure, my brain has been trained to do it by looking at the whitespace to the left of the code. So I need whitespace next to the first line of the block. I don't really look at the braces unless my compiler hints that one is missing, but then it's usually a missing ) after a nested boolean expression ending in a function call.

User avatar
Flumble
Yes Man
Posts: 1939
Joined: Sun Aug 05, 2012 9:35 pm UTC

Re: Coding: Fleeting Thoughts

Postby Flumble » Tue May 23, 2017 4:06 pm UTC

EvanED wrote:... and have a for loop header (or, less commonly, other loops or if) that's multiple lines, I do want the opening brace on a separate line or the body blends into the header.

Hadn't thought about that. Then again, a multi-line for loop header screams reformatting (if it's a rare code style) or restructuring (if the code formatter wraps the line because it's too long, implying you should extract some expressions from the header).

EvanED
Posts: 4324
Joined: Mon Aug 07, 2006 6:28 am UTC
Location: Madison, WI
Contact:

Re: Coding: Fleeting Thoughts

Postby EvanED » Tue May 23, 2017 4:17 pm UTC

Flumble wrote:
EvanED wrote:... and have a for loop header (or, less commonly, other loops or if) that's multiple lines, I do want the opening brace on a separate line or the body blends into the header.

Hadn't thought about that. Then again, a multi-line for loop header screams reformatting (if it's a rare code style) or restructuring (if the code formatter wraps the line because it's too long, implying you should extract some expressions from the header).

I hit multi-line for loops pretty commonly because of the fact that we are not using C++11 yet for a lot of our code (*frowny face*). So this is pretty common:

Code: Select all

for (thing::const_iterator iter = container.begin();
     iter != container.end(); ++iter)
{
    // whatever
}

That's too long for one line by our coding standard (80 cols; I generally hate that, but in this case it would only take a little bit to get unreasonably long by almost any measure), but there's nothing really that's worth pulling out either. Even if you add a typedef ThingCIter (which on balance I don't like) it only barely fits in our line limits if the loop is at just one level of indent. Pulling out the definition of iter is "solving" a stubbed toe by shooting off your foot with a shotgun.

If the type name thing is a long typename and you're at a couple levels of indent, it could even force the first line there to be split again. I've written for loop headers as long as five lines:

Code: Select all

for (std::vector<something>::const_iterator
        iter = container.beign(),
        end = container.end();
     iter != end;
     ++iter)

The last line doesn't really need to be split out there, but my internal line-breaking algorithm demands it. :-)
Last edited by EvanED on Tue May 23, 2017 4:21 pm UTC, edited 2 times in total.

User avatar
Yakk
Poster with most posts but no title.
Posts: 11045
Joined: Sat Jan 27, 2007 7:27 pm UTC
Location: E pur si muove

Re: Coding: Fleeting Thoughts

Postby Yakk » Tue May 23, 2017 4:18 pm UTC

Code: Select all

for(
  int i =8;
  i != 100;
  ++i
) {
  std::cout << i << "\n";
}

indented sections need an unindent line if reasonable. (I wouldn't make a loop as simple as the above a multi-line header).
One of the painful things about our time is that those who feel certainty are stupid, and those with any imagination and understanding are filled with doubt and indecision - BR

Last edited by JHVH on Fri Oct 23, 4004 BCE 6:17 pm, edited 6 times in total.

Tub
Posts: 300
Joined: Wed Jul 27, 2011 3:13 pm UTC

Re: Coding: Fleeting Thoughts

Postby Tub » Fri Jun 16, 2017 3:22 pm UTC

"There are 2 hard problems in computer science: cache invalidation, naming things, and off-by-1 errors."
If we start numbering those problems at 0, then I'm currently stuck with the first problem: naming things.

This is about graphs. Not networks of vertices and edges. I'm talking about those colorful squiggly lines that usually go sideways, but give managers heart-attacks when they suddenly go down. Things like these.

Google told me that a "chart" is something that may or may not be pie-shaped representing a single quantity, while a "plot" or "graph" relates two different quantities (x/y). A "graph" is a squiggly line representing a function while a "plot" is a bunch of scattered symbols representing a set of 2-dimensional points.

Not that anyone cares about that distinction, but "graph" is the correct word for what I'm doing.

Now I'm having a class that sets up a canvas and draws a nice coordinate system with real arrows and labels and everything. I wisely called the class "Graph", because that's a unique name unlikely to clash with anything.

Then I added a class to draw these squiggly lines into the existing coordinate system. As we remember, those squiggly lines are called "graphs", so I named that class.... hang on.

Which one is the graph? The full thing with coordinate system and everything? Or just one squiggly line? And what's the name of the other thing?

Please advise. I'd prefer to refactor this before I have to commit a "SquigglyLine" class into the eternal git history.

User avatar
Yakk
Poster with most posts but no title.
Posts: 11045
Joined: Sat Jan 27, 2007 7:27 pm UTC
Location: E pur si muove

Re: Coding: Fleeting Thoughts

Postby Yakk » Fri Jun 16, 2017 3:53 pm UTC

Code: Select all

namespace Graph {
  struct Graph;
  struct Line;
  struct Axis;
}
One of the painful things about our time is that those who feel certainty are stupid, and those with any imagination and understanding are filled with doubt and indecision - BR

Last edited by JHVH on Fri Oct 23, 4004 BCE 6:17 pm, edited 6 times in total.

User avatar
ucim
Posts: 5507
Joined: Fri Sep 28, 2012 3:23 pm UTC
Location: The One True Thread

Re: Coding: Fleeting Thoughts

Postby ucim » Fri Jun 16, 2017 5:03 pm UTC

Tub wrote:Please advise. I'd prefer to refactor this before I have to commit a "SquigglyLine" class into the eternal git history.
"SquigglyLine" is so wonderful it's worth almost anything for an excuse to create such a class. :) Of course, if this is used for a graph of mortgage requirements, the specific case would have to be a "SquigglyLien". And if it's a graph of normal modes of buildings in an earthquake, that specific instance would have to be called "SquigglyLean".

But yes, I feel your pain, having run into this many times (sometimes many levels deep). It doesn't help when it's tied to a database whose tables (should) share the same name as the variable used to reference it.

Jose
Order of the Sillies, Honoris Causam - bestowed by charlie_grumbles on NP 859 * OTTscar winner: Wordsmith - bestowed by yappobiscuts and the OTT on NP 1832 * Ecclesiastical Calendar of the Order of the Holy Contradiction * Please help addams if you can. She needs all of us.

User avatar
Sizik
Posts: 1146
Joined: Wed Aug 27, 2008 3:48 am UTC

Re: Coding: Fleeting Thoughts

Postby Sizik » Fri Jun 16, 2017 5:37 pm UTC

The graph is just the squiggly line, and the coordinate axes are only there to show which part of the graph you're displaying. Thus, rename the part that does the coordinate system to "GraphDisplay", and the actual line to "Graph"
gmalivuk wrote:
King Author wrote:If space (rather, distance) is an illusion, it'd be possible for one meta-me to experience both body's sensory inputs.
Yes. And if wishes were horses, wishing wells would fill up very quickly with drowned horses.

User avatar
Yakk
Poster with most posts but no title.
Posts: 11045
Joined: Sat Jan 27, 2007 7:27 pm UTC
Location: E pur si muove

Re: Coding: Fleeting Thoughts

Postby Yakk » Fri Jun 16, 2017 5:39 pm UTC

This is neat:
https://www.youtube.com/watch?v=ZsryQp0 ... Jb4dY6nN1D
a reasonably good performance immutable random-access container with fast random-insert and delete, iteration, and indexed lookup.

The idea is that with the right datastructure, huge immutable "vector"s are actually cheap to modify and splice.

It is a tree -- a almost-full 32-fold branching tree, with cash-friendly sized leaf nodes for the data. You can get at a self-mutating version for temporary work, or use rvalue semantics to self-mutate nodes with a reference count of 1.

I'm tempted to write a simple immutable sorted-map on top of it; just have key/value pairs, and insert sorted in the middle.
One of the painful things about our time is that those who feel certainty are stupid, and those with any imagination and understanding are filled with doubt and indecision - BR

Last edited by JHVH on Fri Oct 23, 4004 BCE 6:17 pm, edited 6 times in total.

Tub
Posts: 300
Joined: Wed Jul 27, 2011 3:13 pm UTC

Re: Coding: Fleeting Thoughts

Postby Tub » Fri Jun 16, 2017 11:38 pm UTC

Sizik wrote:The graph is just the squiggly line, and the coordinate axes are only there to show which part of the graph you're displaying. Thus, rename the part that does the coordinate system to "GraphDisplay", and the actual line to "Graph"

Thanks. I was afraid I'd end up with something as boring as GraphDisplay.
Oh well, maybe I'll have more fun with the cache invalidation.

Yakk wrote:This is neat:

Meh. Any sufficiently wide tree is O(1) if you wave your hands fast enough. You can even publish papers about B+ trees where your benchmark only counts leaf accesses, because any inner node will surely be in memory and thus free to use. Don't worry, that'll get through peer review.

For the performance hit to be small, he needs his data to be large enough that cache misses are frequent, giving him enough CPU cycles to do the extra work. He also needs to benchmark on an idle system so that no other task will claim those cycles. And even then his benchmarks appear to have a performance hit of >2x against plain std::vector - but of course he's been handwaving those away, too.

What disappoints me most is his lack of an actual use case. Implementing a text editor on a vector<char>? Sure, with this special vector, you can do that. But if you want syntax highlighting or any kind of formatting, then a vector<char> won't do, so it's the wrong approach for a real-world editor. I'd also bet that his editor will burn if I feed it very long lines of combined unicode characters.
Looking at the applications on my computer that support asynchronous lock-free saving and unlimited undo.. immutable data structures might be a good fit for some of them, but none of them should be implemented on top of a giant vector.

Yakk wrote:I'm tempted to write a simple immutable sorted-map on top of it; just have key/value pairs, and insert sorted in the middle.

A sorted tree on top of an array on top of a sorted tree? I suggest removing the middle man. Implementing an immutable binary search tree is easy, and it actually has the same complexity as its mutable cousin (no handwaving required!).

EvanED
Posts: 4324
Joined: Mon Aug 07, 2006 6:28 am UTC
Location: Madison, WI
Contact:

Re: Coding: Fleeting Thoughts

Postby EvanED » Sat Jun 17, 2017 1:02 am UTC

Tub wrote:For the performance hit to be small, he needs his data to be large enough that cache misses are frequent, giving him enough CPU cycles to do the extra work.
You're comparing however the performance hit to the mutable version. If you need the persistence, there's a lot of good stuff in the talk. Even if you don't outright need it, 2x is really pretty good. There are a couple different techniques in that talk that I'm wondering if I can take and use in the code base in my job. Because yes, you can implement your own binary tree based map... but it'll be slow. That's just the way narrow trees are, because they straight up murder your cache. Cutting the depth of the tree may very well be extremely beneficial. (I have experience with the slowness of a persistent self-balancing binary search tree dictionary. It's not hard for a substantial proportion of your runtime to go into the tree operations themselves.)

I've wondered if a B-tree, or something like it, would be a better base for an immutable sorted map, and I think there's a good chance it would be. But I haven't had the opportunity yet to experiment with that.

Yakk wrote:I'm tempted to write a simple immutable sorted-map on top of it; just have key/value pairs, and insert sorted in the middle.
My guess is that you could do a lot better. The problem I suspect that idea has is the following. All the keys would all be stored (only stored) at the leaves. So when you do a binary search over the vector, you'll have to traverse down the tree at each probe. With something like a B-tree, you only traverse down the relevant path.

Tub
Posts: 300
Joined: Wed Jul 27, 2011 3:13 pm UTC

Re: Coding: Fleeting Thoughts

Postby Tub » Sat Jun 17, 2017 7:31 am UTC

Let me clarify my issues about the talk:

a) he refuses to educate the viewer about performance issues. Every time he mentions performance, he acts as if there's no performance hit at all. Of course there must be one, but instead of talking about it, he does his usual handwaving and skipping the issue. I know you have to sell your talks, but I'd appreciate being honest about the costs, the situations where it's a good solution and even the situations where it isn't. A text editor is a situation where it isn't.

b) He skips the details of the data structure. It's a maximally filled tree, but then it suddenly isn't, but still has constraints about the filling degree.. ? Did he just re-invent the B+ tree or what?
I realize that I've probably spent more time with trees than most of his target audience, but I wanted to see those details. The concept of using a wide tree to improve cache locality is at least 45 years old, so what's new?

Now is his immutable array the greatest thing since sliced bread, or is it a useless gimmick? I don't know, because he skipped the interesting issues. And if someone posts an overly positive talk about something, I tend to respond with an overly negative opinion on a forum. That doesn't mean that I consider it to be completely useless, it just means that he raised enough red flags that I'm less than optimistic about investing time for a deeper evaluation.

EvanED wrote:Because yes, you can implement your own binary tree based map... but it'll be slow. That's just the way narrow trees are, because they straight up murder your cache. Cutting the depth of the tree may very well be extremely beneficial.

Yes, widening a tree is good for cache locality, but non-binary trees obviously have entirely different balancing techniques. If you need a persistent search tree, there are multiple techniques worth researching, all with different tradeoffs.
You can use a custom allocator to pack binary nodes into cachelines, saving memory vs the wide tree, but making it difficult to reason about maximum or average cache misses per operation.
You can use a MVB-Tree, giving you an immutable interface on top of a mutable datastructure.
You can use a B or B+-Tree with COW. You can use his tree (whatever it is) with COW. But the C in COW is an overhead of >1kB for each operation, which will straight up murder your cache and its parents. Do you plan to do more than a million operations on that tree? The COW approaches are only valid if you keep a limited number of old versions (i.e. not in a freaking text editor!).

I'm just saying.. don't base your decisions on a youtube video that's clearly biased.

EvanED wrote:
Yakk wrote:I'm tempted to write a simple immutable sorted-map on top of it; just have key/value pairs, and insert sorted in the middle.
My guess is that you could do a lot better. The problem I suspect that idea has is the following. All the keys would all be stored (only stored) at the leaves. So when you do a binary search over the vector, you'll have to traverse down the tree at each probe.

Exactly. I suggested a binary tree as the simplest alternative, but of course a B/B+ tree works, too. All of the variants mentioned above should be faster than doing binary searches on a search tree.

User avatar
Xenomortis
Not actually a special flower.
Posts: 1394
Joined: Thu Oct 11, 2012 8:47 am UTC

Re: Coding: Fleeting Thoughts

Postby Xenomortis » Sat Jun 17, 2017 9:40 am UTC

Tub wrote:Please advise. I'd prefer to refactor this before I have to commit a "SquigglyLine" class into the eternal git history.

I think the term used at work is "LinePlot". Or maybe it's "Trace".
I actually have no idea how that shit works.
Image

User avatar
ahammel
My Little Cabbage
Posts: 2135
Joined: Mon Jan 30, 2012 12:46 am UTC
Location: Vancouver BC
Contact:

Re: Coding: Fleeting Thoughts

Postby ahammel » Sat Jun 17, 2017 5:11 pm UTC

Database theory question: what's the best way to represent a relationship between users and teams if every user has exactly one primary team and zero or more secondary teams?

Our current schema looks like this:

Code: Select all

+------+-----------------+    +-----------+-------------------+
| user |                 |    | user_team |                   |
+------+-----------------+    +-----------+-------------------+
| id   | primary_team_id |    | user_id   | secondary_team_id |
+------+-----------------+    +-----------+-------------------+
| 1    | 1               |    | 1         | 2                 |
+------+-----------------+    +-----------+-------------------+
Which fits all the constraints, but makes getting all the users in a team somewhat awkward:

Code: Select all

SELECT DISTINCT u.*
FROM user u
  LEFT JOIN user_team ut
    ON u.id = ut.user_id
WHERE
  u.primary_team_id = ?
  OR
  u.secondary_team_id = ?
There's also nothing preventing a user to be a member of a team in two different ways (primary and secondary), which doesn't seem right.

I don't think this is an improvement:

Code: Select all

+------+   +-----------+---------+------------+
| user |   | user_team |         |            |
+------+   +-----------+---------+------------+
| id   |   | user_id   | team_id | is_primary |
+------+   +-----------+---------+------------+
| 1    |   | 1         | 1       | TRUE       |
+------+   | 1         | 2       | FALSE      |
           +-----------+---------+------------+
Getting all of the users in a team looks a little nicer:

Code: Select all

SELECT DISTINCT u.*
FROM user u
  JOIN user_team ut
    ON u.id = ut.user_id
WHERE
  ut.team_id = ?

But enforcing the 1:1 user:primary_team constraint seems harder.

This looks worse as well:

Code: Select all

+------+   +-------------------+---------+   +---------------------+---------+
| user |   | user_primary_team |         |   | user_secondary_team |         |
+------+   +-------------------+---------+   +---------------------+---------+
| id   |   | user_id           | team_id |   | user_id             | team_id |
+------+   +-------------------+---------+   +---------------------+---------+
| 1    |   | 1                 | 1       |   | 1                   | 2       |
+------+   +-------------------+---------+   +---------------------+---------+
The users-in-team query looks a bit uglier:

Code: Select all

SELECT DISTINCT u.*
FROM user u
  JOIN user_primary_team upt
    ON u.id = upt.user_id
  LEFT JOIN user_secondary_team ust
    ON u.id = ust.user_id
WHERE
  upt.team_id = ?
  OR
  ust.team_id = ?
You can make sure each user has exactly one primary team with a foreign key constraint and a uniqueness constraint, but I think that just makes it equivalent to the first schema, just with an extra table. And you can still get the update anomaly where one of the user's secondary teams is also the primary team.
He/Him/His/Alex
God damn these electric sex pants!

User avatar
Thesh
Made to Fuck Dinosaurs
Posts: 5442
Joined: Tue Jan 12, 2010 1:55 am UTC
Location: Colorado

Re: Coding: Fleeting Thoughts

Postby Thesh » Sat Jun 17, 2017 5:22 pm UTC

For starters, you should have: users, teams, user_teams (many-to-many). Within user_teams, I would have a nullable integral type, is_primary, with a unique constraint on (user,is_primary) where null is treated as false and 1 is treated as true and a check constraint preventing other values.
Honesty replaced by greed, they gave us the reason to fight and bleed
They try to torch our faith and hope, spit at our presence and detest our goals

User avatar
ahammel
My Little Cabbage
Posts: 2135
Joined: Mon Jan 30, 2012 12:46 am UTC
Location: Vancouver BC
Contact:

Re: Coding: Fleeting Thoughts

Postby ahammel » Sat Jun 17, 2017 5:58 pm UTC

Thesh wrote:For starters, you should have: users, teams, user_teams (many-to-many). Within user_teams, I would have a nullable integral type, is_primary, with a unique constraint on (user,is_primary) where null is treated as false and 1 is treated as true and a check constraint preventing other values.
Oh neat, I didn't know about the nullable unique constraint trick.

I had this thought in the shower. I'm not sure if it's an improvement:

Code: Select all

+------+   +-----------+---------+---------+   +-------------------+--------------+
| user |   | user_team |         |         |   | user_primary_team |              |
+------+   +-----------+---------+---------+   +-------------------+--------------+
| id   |   | id        | user_id | team_id |   | user_id           | user_team_id |
+------+   +-----------+---------+---------+   +-------------------+--------------+
| Dana |   | 1         | Dana    | Alpha   |   | Dana              | 1            |
+------+   | 2         | Dana    | Bravo   |   +-------------------+--------------+
           +-----------+---------+---------+
user_primary_team is 1:1 wih user and user_team, unique constraint on (user_id,user_team_id)

The queries seem pretty natural:

Code: Select all

-- All user's teams
SELECT ut.team_id
FROM user u
  JOIN user_team ut
    ON u.id = ut.user_id
WHERE
  user.id = ?

-- User's primary team
SELECT user_team.team_id
FROM user
  JOIN user_primary_team
    ON user.id = user_primary_team.user_id
  JOIN user_team
    ON user_primary_team.user_team_id = user_team.id
WHERE
  user.id = ?

-- All users for a team
SELECT user.*
FROM user
  JOIN user_team
    ON user.id = user_team.user_id
WHERE
  user_team.team_id = ?


-- All users who have a particular team as their primary
SELECT user_primary_team.user_id
FROM user_primary_team
  JOIN user_team
    ON user_primary_team.user_team_id = user_team.id
WHERE
  user_team.team_id = ?

-- Change primary teams
UPDATE user_primary_team
SET user_team_id=?
WHERE user_id=?
I think there would need to be some hackery to ensure that each `user` has a `user_primary_team` entry, thought.
He/Him/His/Alex
God damn these electric sex pants!

Tub
Posts: 300
Joined: Wed Jul 27, 2011 3:13 pm UTC

Re: Coding: Fleeting Thoughts

Postby Tub » Sat Jun 17, 2017 11:10 pm UTC

ahammel wrote:Oh neat, I didn't know about the nullable unique constraint trick.

It's very useful, but AFAIK not portable. IIRC allowing multiple NULL values in a UNIQUE constraint actually violates the sql standard (but don't quote me on that).

ahammel wrote:I had this thought in the shower. I'm not sure if it's an improvement:

You've introduced an artificial key on user_team.id. Artificial keys are rarely an improvement, and this one can be avoided by using multi-column foreign keys.
But you're correct that users can end up without a primary team, in both Thesh's suggestion and in your latest idea - those only prevent users from having multiple primary teams.
If you really want to enforce that constraint in the database, stay with your current implementation, or consider this variation:

user: id, primary_team_id, ...
user_team: user_id, team_id
team: id, ...
(Primary keys underlined.)

Add a foreign key constraint from (user.id, user.primary_team_id) to (user_team.user_id, user_team.team_id)

Guarantees:
- every user must have exactly one primary team, as primary_team_id is not nullable
- every user must have an entry in user_team for their primary team, as guaranteed by the foreign key
- a user cannot leave their primary team, as that would violate the foreign key

Queries:
Your five example queries are straightforward.

Problem:
user FK's into user_team, which FKs into user. You cannot insert rows into either table unless you can convince your DB to defer consistency checks until the end of your transaction.

User avatar
Yakk
Poster with most posts but no title.
Posts: 11045
Joined: Sat Jan 27, 2007 7:27 pm UTC
Location: E pur si muove

Re: Coding: Fleeting Thoughts

Postby Yakk » Mon Jun 19, 2017 8:40 am UTC

Tub wrote:b) He skips the details of the data structure. It's a maximally filled tree, but then it suddenly isn't, but still has constraints about the filling degree.. ? Did he just re-invent the B+ tree or what?

He named the data structure. This is just "I implemented it in C++ and it worked pretty well".

Here is a paper on the data structure:
https://infoscience.epfl.ch/record/1698 ... MTrees.pdf

---

And yes, if I implement a map on top of it, it will be far from perfect performance; but if this talk is right, it should be ok performance.

Flat vector maps are faster than traditional binary tree maps. If this is 2x slower than a vector, yet permits log speed inserts in the middle, then it might end up being faster than a std::map. That isn't a high bar, I will admit, but an immutable data structure faster than a std::map is nothing to sneeze at.

---

Changes do cost a bit of storage. You can either drop changes to keep the cost down, or you can mix compact "input logging" and snapshots to generate a full history, or combine the two.

An undo step every character probably isn't practical.

The datastructure is an array of lines. Naturally extremely long lines are going to break it; it is a tech demo, not a real product. I see nothing *hard* about making the lines be something different than a std::string, but it would just bloat the size of the tech demo? You don't have to solve every problem for a tech demo to be of interest.
One of the painful things about our time is that those who feel certainty are stupid, and those with any imagination and understanding are filled with doubt and indecision - BR

Last edited by JHVH on Fri Oct 23, 4004 BCE 6:17 pm, edited 6 times in total.

User avatar
Xenomortis
Not actually a special flower.
Posts: 1394
Joined: Thu Oct 11, 2012 8:47 am UTC

Re: Coding: Fleeting Thoughts

Postby Xenomortis » Wed Jun 21, 2017 9:55 am UTC

Code: Select all

try:
    # some lines that might raise an exception
except:
    raise SomeUselessExceptionClass("Some useless message")

Thanks for hiding what went wrong - you've made everyone's life so much nicer by squashing that pesky error trace.
Image

Nyktos
Posts: 138
Joined: Mon Mar 02, 2009 4:02 pm UTC

Re: Coding: Fleeting Thoughts

Postby Nyktos » Thu Jun 22, 2017 3:48 pm UTC

I assume there's a good chance you're stuck on Python 2, but in modern versions you'd see both tracebacks by default.

User avatar
Xenomortis
Not actually a special flower.
Posts: 1394
Joined: Thu Oct 11, 2012 8:47 am UTC

Re: Coding: Fleeting Thoughts

Postby Xenomortis » Thu Jun 22, 2017 4:36 pm UTC

Yeah, the version isn't changing anytime soon.
There is a solution:

Code: Select all

...
except Exception e:
    raise MyException, MyException(e), sys.exc_info[2] # traceback

But I still think "what's the point"?
Just let the exception bubble up - stop wrapping things up in useless exception classes.
Image

User avatar
ahammel
My Little Cabbage
Posts: 2135
Joined: Mon Jan 30, 2012 12:46 am UTC
Location: Vancouver BC
Contact:

Re: Coding: Fleeting Thoughts

Postby ahammel » Thu Jun 22, 2017 7:19 pm UTC

Tub wrote:If you really want to enforce that constraint in the database, stay with your current implementation, or consider this variation:
That's a neat solution, thanks for your help.
Problem:
user FK's into user_team, which FKs into user. You cannot insert rows into either table unless you can convince your DB to defer consistency checks until the end of your transaction.
Every day I am sad that I have to use MySQL.
He/Him/His/Alex
God damn these electric sex pants!

User avatar
Xeio
Friends, Faidites, Countrymen
Posts: 5086
Joined: Wed Jul 25, 2007 11:12 am UTC
Location: C:\Users\Xeio\
Contact:

Re: Coding: Fleeting Thoughts

Postby Xeio » Thu Jun 22, 2017 9:09 pm UTC

Sometimes I have to resist really really hard not to take a hacksaw to a file when I see how bad the code inside it is.

Like when literally every call to a private method uses the same arguments that are class members... why does it even have arguments? Oh because it's static... wait and there's a static class member which is only initialized by an instance method... good thing only one instance ever lives at once...

Wait, and why are the arguments strings when the object you're passing is always an int and calling .ToString()? Why is the method assuming that the passed string could be a range of values rather than a single value and having code paths to handle something that literally never happens?

Code: Select all

startDate.ToString() == "1/1/0001 12:00:00 AM"
WHY IS THIS A STRING COMPARISON.

I don't even want to look at any more parts of the file unrelated to my bug... I've already fixed/refactored a few things I probably shouldn't have but are just so bad.

User avatar
Flumble
Yes Man
Posts: 1939
Joined: Sun Aug 05, 2012 9:35 pm UTC

Re: Coding: Fleeting Thoughts

Postby Flumble » Thu Jun 22, 2017 10:42 pm UTC

Xeio wrote:

Code: Select all

startDate.ToString() == "1/1/0001 12:00:00 AM"
WHY IS THIS A STRING COMPARISON.

It's to check whether the system is set to the right locale. :mrgreen:

I feel sorry for your eyes.

User avatar
ucim
Posts: 5507
Joined: Fri Sep 28, 2012 3:23 pm UTC
Location: The One True Thread

Re: Coding: Fleeting Thoughts

Postby ucim » Tue Jul 11, 2017 12:28 am UTC

The following new (one hour) video (from the NDC conferences):
https://www.youtube.com/watch?v=MiLAE6HMr10
Spoiler:
From the youtube page:
Published on Jul 10, 2017

The web platform never stops. Every few months, the W3C and browser vendors unload great big bundles of shiny new toys for web developers everywhere.

New JavaScript API standards emerging in 2017 make the web suitable for truly slick applications, having access to many of the same OS and hardware features as native apps, offline or online.

This talk will be an almost-continuous series of demos of recent and upcoming JavaScript APIs and features. You'll learn of new possibilities that will hopefully be relevant to the apps you build.


Note: Due to technical issues there is no picture from the stage throughout this talk.
...introduces some new client-side web capabilities. The first part is about service workers. These are methods that allow a web page scripts to execute code even when the user is not on the web page, or is completely offline. Though they have some legitimate uses, it seems to me that this is ripe for abuse, especially if the hapless user does not know that leaving a website doesn't stop that site from running what to the user is arbitrary code on their computer.

Why should I not be alarmed?

Jose
Order of the Sillies, Honoris Causam - bestowed by charlie_grumbles on NP 859 * OTTscar winner: Wordsmith - bestowed by yappobiscuts and the OTT on NP 1832 * Ecclesiastical Calendar of the Order of the Holy Contradiction * Please help addams if you can. She needs all of us.

commodorejohn
Posts: 944
Joined: Thu Dec 10, 2009 6:21 pm UTC
Location: Placerville, CA
Contact:

Re: Coding: Fleeting Thoughts

Postby commodorejohn » Tue Jul 11, 2017 2:53 am UTC

Well that's the worst idea I've heard today, and today was the day where the President's son tried to use "yeah, I attempted to collude with the Russians, but I didn't get any useful dirt, so...no harm no foul?" as his official line of defense.
"'Legacy code' often differs from its suggested alternative by actually working and scaling."
- Bjarne Stroustrup
www.commodorejohn.com - in case you were wondering, which you probably weren't.

User avatar
Flumble
Yes Man
Posts: 1939
Joined: Sun Aug 05, 2012 9:35 pm UTC

Re: Coding: Fleeting Thoughts

Postby Flumble » Tue Jul 11, 2017 11:33 am UTC

I take it the browser will ask the user "do you want this site to drain your battery, waste your bandwidth and track you forever?" before running a service worker. Right? :roll:


Return to “Coding”

Who is online

Users browsing this forum: No registered users and 7 guests