Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
Athas
Aug 6, 2007

fuck that joker

shrughes posted:

Well, reading things about "checking in code for the night" makes it sound like people are all working on the same branch or something... And having the timescale between "commits" being hours rather than minutes... :/

Do you really think it's useful to commit every few minutes?

Adbot
ADBOT LOVES YOU

Athas
Aug 6, 2007

fuck that joker
I like ponies :downs:

Athas fucked around with this message at 06:31 on Sep 14, 2009

Athas
Aug 6, 2007

fuck that joker

HFX posted:

Well to be honest, the more I've programmed, the more I like languages which tend to have the most powerful representation as the default (Lisp, Scheme, Haskell) with the ability to constrain to smaller faster machine dependent types when needed.

But said languages are useful because you can drop down to machine-level operations when necessary.

Athas
Aug 6, 2007

fuck that joker

jarito posted:

Right, but that's not what we are complaining about. This is:

code:
void someFunc(var a, var b, var c) 
{
    var d = a.Object.DoSomething();
    d.execute();
}
Using var where the typing information is unneeded is fine, but it gives idiots a crutch to turn C# into a weakly typed language, which it is not.

It is you. You are the horror who codes.

By your logic, the type inference in Haskell also makes it weakly typed.

Athas
Aug 6, 2007

fuck that joker

Janin posted:

Hah, I wish we were using anything as sane as Subversion. Our VCS has no CLI; its only interface is graphical, written in Java Swing, and uses over 200 MiB RAM (from a 1 GiB VM) when idle.

What is the name of this horror? It sounds unbelievable.

Stories like these make me glad to be in academia. Do people set up incredibly awful things? Sure, but they normally can't force you to do the same.

Athas
Aug 6, 2007

fuck that joker

theg sprank posted:

How do you know it doesn't become \exists?

\exists and \forall are an E and an A mirrored across both axes.

Athas
Aug 6, 2007

fuck that joker

Internet Janitor posted:

Oh, PHP. :smith:

What if the next element in the array is the boolean value FALSE?

Edit: :arghfist: :f5:

Athas fucked around with this message at 16:03 on Apr 8, 2010

Athas
Aug 6, 2007

fuck that joker
I just produced this horror:

code:
if [ $(tar tf "$1"|sed 's/\/.*//g'|sort -u|wc -l) -gt 1 ]; then
    echo tarbomb!
fi
It is a snippet of Bourne shell script for checking whether a tarball ($1) extracts to more than a single file/directory.

It is very very gross, but shell scripting is a guilty pleasure for me. It's so dirty.

Athas
Aug 6, 2007

fuck that joker

Aleksei Vasiliev posted:

http://jefferai.org/2013/03/24/too-perfect-a-mirror/
The KDE project very nearly managed to lose all 1500 of their git repositories, if not for one of their servers getting lucky on timing so the sync timed out. The other four servers saw that the main server had been corrupted, so they faithfully deleted their copies. There were no backups.

Well, doesn't every developer have a full copy of the repository they're working on?

Athas
Aug 6, 2007

fuck that joker

Thermopyle posted:

Yep. This is an issue across a lot of fields in science and is part of the reason there's a crisis of sorts with regards to reproducibility. I'm in particular thinking about the more smooshy medical/health/social sciences.

It's a general crisis? I thought I was the only one who cared about it. I'm a computer science student, and my eyes have only recently been opened to the utter atrocity that is the lack of reproducibility in computer science papers. How can this even be science? How can someone publish a benchmark result, be vague about the specifics of their algorithms and implementation, yet not provide any code? Not only can I not reproduce their results, I cannot even reasonably compare my own to theirs! Even when code is available, it is often environment-dependent (with said environment left undocumented) to such a degree that you have no chance of getting it to work. Reproducibility in computer science should be trivial, but instead it is non-existent. I really wish there was a journal, or just a paper database, that only accepted submissions that lived up to some standard of reproducibility.

Athas
Aug 6, 2007

fuck that joker

Carthag posted:

Now by that I cannot abide. Only class names may be capitalized (and constants all-capped).

Speaking of, though, does anyone know why they chose to cap methods in C#? It looks so incredibly wrong to me.

I don't understand why so few languages use semantic casing. In Haskell, variables and functions (i.e. value bindings) must begin with a lowercase letter, while the names of types, typeclasses and similar things must be capitalised. Not sure how the distinction would work in a C-ish language, though. I suppose it could be used to get avoid 'typename' cruft in C++.

Athas
Aug 6, 2007

fuck that joker

Mustach posted:

Since Simula and/or Smalltalk

I think the point is that while all OOP includes polymorphism, there are plenty of non-OO languages that still support polymorphism.

In Haskell, which is certainly not object-oriented by any reasonable measure, there is a way to turn objects into strings. Of course, Haskell does this with type classes. :tinfoil:

Athas
Aug 6, 2007

fuck that joker
Using booleans as integers also has value when working with architectures that are not boring. For example, consider vector machines - they can execute instructions that operate across an array of values, but each element of the array must be processed the same. In essense, this is a very simple 'map' operation.

Consider an expression like this:

code:
let result = map(fn (x) => if x < 0 then f(x) else g(x), a)
This is a map across the input 'a'. You cannot directly execute this on a vector machine, because the function you're mapping with contains a branch, which is a no-no. Instead, you must decompose like this:

code:
let conds = map(fn (x) => x < 0, a)
let fs = map(fn (x) => f(x), a)
let gs = map(fn (x) => g(x), a)
let result = map(fn (cond, v1, v2) => cond * v1 + !cond * v2, conds, fs, gs)
(Actually, you must decompose the final map a bit more, since many systems will not have vector instructions that accept more than two input arrays.)

Interestingly, this is pretty much how GPUs work (in that both branches of a conditional are always taken), although you don't have to perform the above decomposition yourself.

Athas
Aug 6, 2007

fuck that joker

Opinion Haver posted:

What are these strange 'for loops' of which you speak?

code:
> mapM_ (\(i, word) -> putStrLn (show i ++ " " ++ word)) (zip [0..] ["foo", "bar", "baz"])
0 foo
1 bar
2 baz

That is a coding horror (or at least a little goosebumpy). Use forM_ and indentation!

code:
forM_ (zip [0..] ["foo", "bar", "baz"]) $ \(i, word) ->
  putStrLn (show i ++ " " ++ word)
See, much better.

Athas
Aug 6, 2007

fuck that joker

evensevenone posted:

Isn't that why people enter academia?

Yep. Academia here, paid (poorly) to write in Haskell.

Of course, some of that Haskell is written by a post-doc who used to be a Fortran programmer. I could probably grab a few things for this thread...

Athas
Aug 6, 2007

fuck that joker

Internet Janitor posted:

Students are mostly third-year CS students with some experience programming in imperative languages, but many have never used a functional language before.

This is the real horror. How can you be a third-year CS student and not have seen a functional language?

Also, it's cheating to bring in homework code. While correcting operating systems assignments, I've seen bugs you people wouldn't believe. TLBs on fire at the end of a context switch. I watched kernel threads unwittingly created without a stack, as they were functional as long as they never spilled registers or called functions. All that code will be lost in time, like a stack trace in a log file.

Athas
Aug 6, 2007

fuck that joker

JawnV6 posted:

Good. Cram a bunch of ugly global calls into one file and leave the rest of the code base untouched. Don't fork every function or try to cram every bit of state it might ask for into the function signature.

Hello, I write Haskell at my job, and this is pretty much necessary. As for a horror...

code:
runFunNoTrace :: Name -> [Value] -> Prog -> Either InterpreterError [Value]
runFunNoTrace = ((.) . (.) . (.)) fst runFun

Athas
Aug 6, 2007

fuck that joker

Zombywuf posted:

Is it wrong that this makes me think of Total Recall?

Not at all! I was in fact thinking about what to call this pattern, given that its smaller cousin '(.) . (.)' has a pretty obvious name.

Athas
Aug 6, 2007

fuck that joker

LOOK I AM A TURTLE posted:

And triple boobs lets me do the same thing when there are exactly three missing parameters?
code:
let totalRecall = (.) . (.) . (.)
let multiSubtract x y z = x-y-z
let double x = x*2
let multiSubtractAndDouble = double `totalRecall` multiSubtract
I like pointfree style and all, but this is pretty ridiculous. Can Haskell programmers actually read this stuff?

This particular idiom is not too bad, once you know it. You just count the boobs: '(.) . (.)' is composing a function that takes two arguments, '(.) . (.) . (.)' one that takes three, and so on. The biggest problem is that it is not infix. In Haskell, you can turn an ordinary function into an infix operator by surrounding it with backticks:

code:
x `foo` y
This is in many cases very useful. Unfortunately, the syntax only permits you to put names, not expressions, in backticks, so this is a syntax error:

code:
f `(.) . (.)` g
As an aside, it's amazing how many Haskell people suddenly crop up when you start talking about it. For another semi-horror, let's look at how the 'Eq' instances are defined for tuples in GHC. For the non-Haskell people, a 'typeclass' is sort of like an OO interface, and you can declare a given type to be an 'instance' of the interface. For tuples, you need to provide an explicit instance definition for every size of tuple you may need:

code:
deriving instance (Eq  a, Eq  b) => Eq  (a, b)
deriving instance (Eq  a, Eq  b, Eq  c) => Eq  (a, b, c)
deriving instance (Eq  a, Eq  b, Eq  c, Eq  d) => Eq  (a, b, c, d)
deriving instance (Eq  a, Eq  b, Eq  c, Eq  d, Eq  e) => Eq  (a, b, c, d, e)
deriving instance (Eq a, Eq b, Eq c, Eq d, Eq e, Eq f)
               => Eq (a, b, c, d, e, f)
deriving instance (Eq a, Eq b, Eq c, Eq d, Eq e, Eq f, Eq g)
               => Eq (a, b, c, d, e, f, g)
deriving instance (Eq a, Eq b, Eq c, Eq d, Eq e, Eq f, Eq g,
                   Eq h)
               => Eq (a, b, c, d, e, f, g, h)
deriving instance (Eq a, Eq b, Eq c, Eq d, Eq e, Eq f, Eq g,
                   Eq h, Eq i)
               => Eq (a, b, c, d, e, f, g, h, i)
deriving instance (Eq a, Eq b, Eq c, Eq d, Eq e, Eq f, Eq g,
                   Eq h, Eq i, Eq j)
               => Eq (a, b, c, d, e, f, g, h, i, j)
deriving instance (Eq a, Eq b, Eq c, Eq d, Eq e, Eq f, Eq g,
                   Eq h, Eq i, Eq j, Eq k)
               => Eq (a, b, c, d, e, f, g, h, i, j, k)
deriving instance (Eq a, Eq b, Eq c, Eq d, Eq e, Eq f, Eq g,
                   Eq h, Eq i, Eq j, Eq k, Eq l)
               => Eq (a, b, c, d, e, f, g, h, i, j, k, l)
deriving instance (Eq a, Eq b, Eq c, Eq d, Eq e, Eq f, Eq g,
                   Eq h, Eq i, Eq j, Eq k, Eq l, Eq m)
               => Eq (a, b, c, d, e, f, g, h, i, j, k, l, m)
deriving instance (Eq a, Eq b, Eq c, Eq d, Eq e, Eq f, Eq g,
                   Eq h, Eq i, Eq j, Eq k, Eq l, Eq m, Eq n)
               => Eq (a, b, c, d, e, f, g, h, i, j, k, l, m, n)
deriving instance (Eq a, Eq b, Eq c, Eq d, Eq e, Eq f, Eq g,
                   Eq h, Eq i, Eq j, Eq k, Eq l, Eq m, Eq n, Eq o)
               => Eq (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o)
GHC is actually able to derive these instances automatically, but you still need to explicitly need to list every tuple type you want. Hope 15 elements is enough!

(Repeat the above for every type class you want tuples to implement.)

Athas
Aug 6, 2007

fuck that joker

AlsoD posted:

While the type and pattern definition will still need to be recreated for each tuple length, you save the boilerplate for all the other instances. What do you think?

Apart from the fact that you will no longer be able to distinguish (a,(b,c)) from (a,b,c), this is not a bad idea. I've had similar thoughts before.

Athas
Aug 6, 2007

fuck that joker

Otto Skorzeny posted:

Also the fact that the repository makes frankly bizarre assumptions as to where the source lives
code:
@@ -2106,7 +2106,7 @@ yyreduce:
     break;
 
   case 3:
-#line 388 "/Users/chet/src/bash/src/parse.y"
+#line 388 "/usr/src/local/chet/src/bash/bash-4.2-patched/parse.y"
     {
 			  /* Case of regular command, but not a very
 			     interesting one.  Return a NULL command. */
etc

That is generated code.

Athas
Aug 6, 2007

fuck that joker

Soricidus posted:

There's more than one? :ohdear:

Haskell also inserts semicolons (and curly braces) by itself. That's because the Haskell syntax is nominally indentation-based (like Python), but it's internally reduced to a braces-and-semicolon syntax, which is what the grammar proper is defined in terms of. For example:


code:
fartButts = do butts <- gets allButts
               forM butts $ \butt -> do aim butt
                                        fart butt
               return smell
is converted to

code:
fartbutts = do {
              butts <- gets allButts;
              forM butts $ \butt -> do {
                                      aim butt;
                                      fart butt;
                                    };
              return smell;
              }
Or something like that - most Haskell programmers never use the
explicit notation, except if they have to generate Haskell code for some reason

Athas
Aug 6, 2007

fuck that joker

Aleksei Vasiliev posted:

Admirable ideas. Let's take a look at this easily auditable code.
C code:
sv unpack25519(gf o, const u8 *n)
{
  int i;
  FOR(i,16) o[i]=n[2*i]+((i64)n[2*i+1]<<8);
  o[15]&=0x7fff;
}

sv A(gf o,const gf a,const gf b)
{
  int i;
  FOR(i,16) o[i]=a[i]+b[i];
}

sv Z(gf o,const gf a,const gf b)
{
  int i;
  FOR(i,16) o[i]=a[i]-b[i];
}

sv M(gf o,const gf a,const gf b)
{
  i64 i,j,t[31];
  FOR(i,31) t[i]=0;
  FOR(i,16) FOR(j,16) t[i+j]+=a[i]*b[j];
  FOR(i,15) t[i]+=38*t[i+16];
  FOR(i,16) o[i]=t[i];
  car25519(o);
  car25519(o);
}

sv S(gf o,const gf a)
{
  M(o,a,a);
}

sv inv25519(gf o,const gf i)
{
  gf c;
  int a;
  FOR(a,16) c[a]=i[a];
  for(a=253;a>=0;a--) {
    S(c,c);
    if(a!=2&&a!=4) M(c,c,i);
  }
  FOR(a,16) o[a]=c[a];
}

My guess is that these names correspond to procedures in some paper. Anyway, I do not find this hard to read - each function is small and self-contained, and can be audited in isolation.

Edit: For example, the point of the FOR macro is most likely to make it completely clear that the loop is executed an input-insensitive number of times, to eliminate timing attacks.

Athas
Aug 6, 2007

fuck that joker

JawnV6 posted:

Yeah, and it's utterly impossible for any bug to be lurking somewhere between dense 1-line mathematical functions and a higher-level spec composing dozens of them for the simplest possible transaction.

No, but it may be easier for an auditor to ensure that he understands the interactions perfectly. I'm not claiming that anyone should write code this way, just that there's rhyme to the reason for some cases. Is everything in TinySSH written like this?

Athas
Aug 6, 2007

fuck that joker

revmoo posted:

If I see more than a thousand lines in any file that's not a stylesheet I tend to freak out.

Yeah, at my current job, we only have two source files longer than a thousand lines. One is written by someone who isn't really a Haskell programmer, and therefore writes pretty verbose code, and the other... well, the other one should probably be split up. The median number of lines per file is 144; the average is 229.

Athas
Aug 6, 2007

fuck that joker

fritz posted:

I saw a thing the other week where a prof decided to do an experiment where he wrote to authors asking for their software and had a grad student try to build it in under 30 minutes and there were lots and lots of things that wouldn't even compile.

Yes, one of my friends did his masters thesis on embedded GPU programming languages in Haskell. According to him, it was a nightmare even getting the stuff to build and run, and Haskell isn't even that of a tricky language to compile. I think the issue is that research code often depends on obscure libraries or crazy setups.

Athas
Aug 6, 2007

fuck that joker

Paul MaudDib posted:

I always thought something like Erlang might perform well on GPUs.

Erlang uses task parallelism, not data parallelism, so it's not a good fit for GPUs. Great fit for clusters, though.

Athas
Aug 6, 2007

fuck that joker

EAT THE EGGS RICOLA posted:

He has never used a local VM for development, ever.

Hell, I don't either. Unless you mean just having a special set of (known-version) libraries or something?

Athas
Aug 6, 2007

fuck that joker

eithedog posted:

So, which language has naming consistency?

APL. ⌈ is the maximum function, ⌊ is the minimum. Similarly, ⌽ is reversal along the last axis, while ⊖ is along the first axis, and, of course, ⍉ reverses all axes.

The rabbit hole goes all the way, too: ⍎ is the "eval" function. Conceptually, it is "turn text into APL value". What, then, is the behaviour of the obviously inverse symbol, ⍕? Well, it is the pretty-printer, of course, as that turns APL values into text! Oh, and the function for multiplying by π is of course ○.

Athas fucked around with this message at 16:19 on Aug 19, 2014

Athas
Aug 6, 2007

fuck that joker

Sagacity posted:

If this distance algorithm was really generic you'd be able to run it as a CUDA kernel without doing any work but I guess it's not that generic.

...I actually did that for an internship this summer. I used C++ operator overloading to turn what seemed like ordinary functions into functions that actually generated syntax trees, then doing code generation at run-time to generate CUDA kernels, compile them with NVCC, then link them back in and run the code on GPU. I suppose that's a bit of a horror.

Oh, and of course, it also had to be able to turn arrays of structs (like points) into structs of arrays instead. Without the user having to write this vectorisation himself.

Athas
Aug 6, 2007

fuck that joker

hobbesmaster posted:

Except the large character class isn't a "God object" because it's not controlling the entire program's execution. It's just a store of a ton of information here and that's not too bad as things go.

Well, it does seem to contain a huge number of enums for things like (character) classes, races and cultures. Some of these should probably be proper independent classes, as this smacks of some ugly type-case/switch statement somewhere. Or best of all: move that stuff to data files loaded at runtime, rather than baking it statically into the code.

Athas
Aug 6, 2007

fuck that joker

Vanadium posted:

What does bash parse functions out of environment variables in the first place? :ohdear:

It's the only way to export shell functions to subshells. Well, I suppose you could also put them in a magic file somewhere, but you couldn't do something nice like using a proper IPC mechanism, because you do not control how your subshells are started (consider something like the -exec action to find(1)). At the end of the day, it comes down to parsing the functions as text, and the environment is really the only sensible place to put them if you want this feature.

The problem is not as much this dumb feature, as the fact that the feature (and its bugs) were forced upon people who ask for just /bin/sh, expecting just a POSIX shell. Now, on good Unices, /bin/sh is not going to be bash (it's dash on Ubuntu and I think Debian, and something similar on *BSDs), but CentOS/Red Hat seems afflicted.

Stupid operating systems.

Athas
Aug 6, 2007

fuck that joker

pseudorandom name posted:

Or if the legions of broken programs that pass an unsanitized attacker-controlled environment to bash didn't actually do something so idiotic...

They didn't. They passed an environment to /bin/sh, in which they knew that important shell variables (like PATH) were not tampered with. Bash pretends to be /bin/sh, but is not, resulting in this mess.

Athas
Aug 6, 2007

fuck that joker

Illusive gently caress Man posted:

code:
    if (!IS_BIG_ENDIAN) {
        i = 0;
        while (i < ret / sizeof(uint32_t)) {
            *((uint32_t *) ((*raw) + (i * sizeof(uint32_t)))) = htobe32(
                    *((uint32_t * )((*raw) + (i * sizeof(uint32_t)))));
            i++;
        }
    }
im cryeing

This is what I don't understand. Dealing with endianness is so bloody easy in C, so why do people gently caress it up? Here, do it like this:

code:
#ifdef SMALL_ENDIAN
uint32_t from_big_endian(uint32_t in)
{
  uint32_t out;
  char *p_in = (char *) &in;
  char *p_out = (char *) &out;
  p_out[0] = p_in[3];
  p_out[1] = p_in[2];
  p_out[2] = p_in[1];
  p_out[3] = p_in[0];

  return out;
}
#else
uint32_t from_big_endian(uint32_t in)
{
  return in;
}
#endif
Now, there's still plenty of room to bikeshed over this code, but the two basic principles of handling endianness are:

  • Talk about what the serialised representation is/should be, not what the in-memory representation this.
  • Define some bloody functions.

It's really not hard to get right. Why do people gently caress it up?

Athas
Aug 6, 2007

fuck that joker

pseudorandom name posted:

Why are you reimplementing be32toh() and what does that have to do with the coding horror posted?

The bikeshed in question was for a freestanding kernel (no standard library and certainly no POSIX implementation), so I had to write the code.

And isn't the original horror a byte-swapper? I actually didn't read it too closely, but whenever I see impenetrable code saying something about "endian" followed by weird address and/or shift manipulations, I assume that someone misunderstood endianness.

Athas
Aug 6, 2007

fuck that joker

down with slavery posted:

My only question is why

Same reason that Node.js is as popular as it is - people are too lazy to learn a new language.

Athas
Aug 6, 2007

fuck that joker

Mogomra posted:

I don't think anyone is questioning the horror in the code.

Why would anyone post that much, apparently unaltered, closed source code is beyond me, and the rest of this thread.



:thejoke:

Is this source code really something a competitor would want to steal?

(I've never worked on/with closed source code, so I don't have much intuitive understanding as to why it's supposed to be sensitive. Most code is almost useless without its documentation or supporting environment anyway, and if it's not, you probably can't claim you wrote it without it being trivially obvious that you did not.)

Athas
Aug 6, 2007

fuck that joker

JawnV6 posted:

How does the anti-switch camp implement FSM's? Do you just resign yourself to a Mealy taste?

Tail recursion, coroutines or lookup tables of function pointers.

Or in languages that are not terrible: pattern matching on sum types.

Athas
Aug 6, 2007

fuck that joker

Joda posted:

E: In what way is it even a variable?

If it's not a constant, then it's a variable, and if you're writing a program in which this is a constant, then your design is weird. If it has to be an lvalue to be a variable, then functional languages have no variables.

Adbot
ADBOT LOVES YOU

Athas
Aug 6, 2007

fuck that joker

Plorkyeran posted:

Is it even possible to write a serious crypto lib in non-unsafe Haskell? The entire design of the language kind of falls apart once you consider CPU time spent to be an observable side effect.

Right, don't write crypto in Haskell. Most high-level languages are probably going to be vulnerable to side channel attacks. Also, don't store keys or the like in memory that you cannot zero as soon as you are done with it. (This also means "don't store keys in movable memory, such as many GC'ed heaps".) Most crypto is quite simple in terms of data structures, so there is really no point to implementing the algorithms in languages more expressive than C anyway.

It depends on how paranoid you are, of course.

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply