Coding: Fleeting Thoughts

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

Moderators: phlip, Moderators General, Prelates

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 Jul 31, 2014 5:09 am UTC

KnightExemplar wrote:The problem with the second definition you have is that the Lisp-based languages have very specific scope rules, because they either have (set!) (for Scheme) or (setq) (for Lisp). So the latter definition doesn't apply. Any definition of "functional" that puts Scheme and Common Lisp outside of its definition just doesn't cut it for me.

Common Lisp has all kinds of destructive operations, not just the set- family of functions. The use of HOFs in practice (at least in my limited experience) is much rarer than the use of the loop macro in CL. The spec doesn't mention tail recursion. Hell, it even has goto.

I'm perfectly happy to say that Scheme puts more of an emphasis on functional programming than CL.
He/Him/His/Alex
God damn these electric sex pants!

KnightExemplar
Posts: 5494
Joined: Sun Dec 26, 2010 1:58 pm UTC

Re: Coding: Fleeting Thoughts

Postby KnightExemplar » Thu Jul 31, 2014 5:13 am UTC

Oh, as for my current fleeting thought (the reason why I came to this thread...)

I was trying to remember a subject from college. They're called Monotone Piecewise Cubic Interpolations, and they're fucking awesome. Cubic Splines suck ass, and it bothers me that they're so much more popular.

http://en.wikipedia.org/wiki/Monotone_c ... erpolation

Look ma! No more "ringing" issues! Monotone guarantees the lack of "ringing" in any spline, and also preserves monotone behavior. (If the curve it is fitting is monotone, then the interpolation will be monotone as well). So they're much more natural than other splines IMO.
First Strike +1/+1 and Indestructible.

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

Re: Coding: Fleeting Thoughts

Postby EvanED » Thu Jul 31, 2014 5:54 am UTC

KnightExemplar wrote:Fair enough. IIRC, Compliant Scheme actually rebuilds the continuation, right? (Call/cc is confusing sometimes...)
I don't actually know what a high-performance implementation would do, to be honest. The easiest thing would be to just allocate stack frames on the heap: then when you construct a closure it gets a reference to the stack frame and the GC proceeds as normal. So the frame for f can stick around after f returns. There may not be a way around doing something similar to that.
I don't think you had that discussion with me, but I can see that as an argument.
I'm guessing it was mostly with Yakk then, probably with some other input too.

schapel
Posts: 244
Joined: Fri Jun 13, 2014 1:33 am UTC

Re: Coding: Fleeting Thoughts

Postby schapel » Thu Jul 31, 2014 5:59 pm UTC

Triple Log wrote:Knight was likely right though in that I should jsut keep trying to hammer my way through C since I am already making progress.

I'll come to this forum to whine about my crappy code. Hooray!

I'm willing to take a look at some code you're having a problem with and help you out. I get the impression you're having trouble with just a few core concepts, and once you understand those, you'll find it much easier. If you don't feel comfortable posting it here, you can PM me.

If you continue finding it difficult, many people have trouble with the kind of thinking that programming takes. Frankly, if you don't find it fascinating, it can be incredibly tedious. Learning programming well is something that takes lots of time and effort, and if you just don't enjoy it, don't torture yourself. Find something you like to do, and then putting in the effort will be much easier. It won't even be like effort if you enjoy it enough.

Also, C is one of the more difficult languages to learn as a first language, because it combines both high-level and low-level concepts. At least you're not trying to learn C++. :D

Triple Log
Posts: 33
Joined: Thu Jul 17, 2014 5:32 pm UTC

Re: Coding: Fleeting Thoughts

Postby Triple Log » Thu Jul 31, 2014 6:19 pm UTC

schapel wrote:
Triple Log wrote:Knight was likely right though in that I should jsut keep trying to hammer my way through C since I am already making progress.

I'll come to this forum to whine about my crappy code. Hooray!

I'm willing to take a look at some code you're having a problem with and help you out. I get the impression you're having trouble with just a few core concepts, and once you understand those, you'll find it much easier. If you don't feel comfortable posting it here, you can PM me.

If you continue finding it difficult, many people have trouble with the kind of thinking that programming takes. Frankly, if you don't find it fascinating, it can be incredibly tedious. Learning programming well is something that takes lots of time and effort, and if you just don't enjoy it, don't torture yourself. Find something you like to do, and then putting in the effort will be much easier. It won't even be like effort if you enjoy it enough.

Also, C is one of the more difficult languages to learn as a first language, because it combines both high-level and low-level concepts. At least you're not trying to learn C++. :D

Nothing at the moment. I'm learning about scopes (external, internal, block) and seem to understand them.
Spoiler:
static external is for all files in a multifile program
static internal (or just internal) is just one file but all functions within
local is just that function (or block)


Also, is anyone else having trouble submitting replies? I just get the loading circle on my tab and it never moves to the "submitted" page. It is submitting but I just go back to the thread after waiting a second and it's there.

MostlyHarmless
Posts: 154
Joined: Sun Oct 22, 2006 4:29 am UTC

Re: Coding: Fleeting Thoughts

Postby MostlyHarmless » Thu Jul 31, 2014 6:25 pm UTC

I'm very proud of myself this morning. I made a python script to download a few hundred zip files, extract them somewhere, then delete the zip files. Not much, I know, but this is my first working python code and the first time in about a decade that I've coded anything besides numerical stuff. Even better, the whole process took less time than it would have to download them all by hand.

User avatar
Jplus
Posts: 1721
Joined: Wed Apr 21, 2010 12:29 pm UTC
Location: Netherlands

Re: Coding: Fleeting Thoughts

Postby Jplus » Thu Jul 31, 2014 10:48 pm UTC

ahammel wrote:
Triple Log wrote:The fact that everything I learn now is just a basic "toy" as you called it is demotivating. I want to do cool things that are useful!

Sorry, but skipping the toy programs and going right into full-featured software that people will be tripping over themselves to use isn't really an option. Legos before skyscrapers.

I feel this can't be stressed enough. Toys are always the best way to learn something, regardless of what it is. Here, have at some wonderful programming toys...
Manufactoria
KOHCTPYKTOP
The Codex of Alchemical Engineering
Minecraft (payware)
Cargo-Bot (iPad only)

EvanED wrote:
KnightExemplar wrote:
Again, I'd say the most important characteristic is the ability to easilyish create closures -- though again, there are a couple possible meanings of "closure", and C++ only meets the weaker one.
Wait, what about C++0x closures don't match up with the proper definition? C++ closures can capture both by value and by reference, so they're at least as good as Scheme closures.
We've had this discussion before and I think largely agreed to disagree (or at least I had it with some people here), but my position is that C++ "closures" don't completely close their environment because it is possible for that environment to go away while the closure still exists and is callable (until it clobbers your stack). Just "close" over some local variables and return the closure from a function.
I might have been involved in that one. You are right insofar that C++11 standardized closures don't behave like proper closures out-of-the-box. However, you can have any behaviour you want if you explicitly decide to allocate things on the stack and use smart pointers or a tracing garbage collector. Or reach for something fancier like Boost.Context or Boost.Phoenix. It's not like C++ can't do it.

KnightExemplar wrote:Monotone Piecewise Cubic Interpolations

I guess it's friendly to the (flawed) human expectations. But what does it do to the spectrum of the signal?


@Triple Log: If you are looking for something relatively simple and playful that is reasonably straightforward to do in C and which is still useful for other people, you might find something over at the red spider project. Looking throught the issue list, I think this or this could be suitable. Looking further through our list of free ideas, I also find "a program that returns a random xkcd comic number on exit", "a command called 'beret' that does... SOMETHING", "a 'foreach' command" (for the command line, to repeatedly run another command for each line of some stream of text) and "a command that displays xkcd comics".

MostlyHarmless wrote:I'm very proud of myself this morning. I made a python script to download a few hundred zip files, extract them somewhere, then delete the zip files. Not much, I know, but this is my first working python code and the first time in about a decade that I've coded anything besides numerical stuff. Even better, the whole process took less time than it would have to download them all by hand.

Kudos for you. :-)
"There are only two hard problems in computer science: cache coherence, naming things, and off-by-one errors." (Phil Karlton and Leon Bambrick)

coding and xkcd combined

(Julian/Julian's)

User avatar
chridd
Has a vermicelli title
Posts: 843
Joined: Tue Aug 19, 2008 10:07 am UTC
Location: ...Earth, I guess?
Contact:

Re: Coding: Fleeting Thoughts

Postby chridd » Thu Jul 31, 2014 11:05 pm UTC

EvanED wrote:
I don't think you had that discussion with me, but I can see that as an argument.
I'm guessing it was mostly with Yakk then, probably with some other input too.
It was here: viewtopic.php?p=3531592#p3531592

I still think that, since closures came from functional programming, and pure functional languages (some of which definitely have closures) treat everything as a value, it doesn't make sense not to consider C++ by-value closures to be real closures.
~ chri d. d. /tʃɹɪ.di.di/ (Phonotactics, schmphonotactics) · she · Forum game scores
mittfh wrote:I wish this post was very quotable...

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

Re: Coding: Fleeting Thoughts

Postby EvanED » Fri Aug 01, 2014 3:38 am UTC

Jplus wrote:I feel this can't be stressed enough. Toys are always the best way to learn something, regardless of what it is. Here, have at some wonderful programming toys...
Manufactoria
KOHCTPYKTOP
The Codex of Alchemical Engineering
Minecraft (payware)
Cargo-Bot (iPad only)
I am a fan of SpaceChem. :-)

I might have been involved in that one. You are right insofar that C++11 standardized closures don't behave like proper closures out-of-the-box. However, you can have any behaviour you want if you explicitly decide to allocate things on the stack and use smart pointers or a tracing garbage collector. Or reach for something fancier like Boost.Context or Boost.Phoenix. It's not like C++ can't do it.
And I still think that by the time you get there, you might as well say "C supports closures because you can just wrap up the values you need in a struct then pass it and a function pointer together, and if even that is too much work, just use libffi."

chridd wrote:I still think that, since closures came from functional programming, and pure functional languages (some of which definitely have closures) treat everything as a value, it doesn't make sense not to consider C++ by-value closures to be real closures.
That's actually pretty reasonable, though I maintain my position.

:-)

KnightExemplar
Posts: 5494
Joined: Sun Dec 26, 2010 1:58 pm UTC

Re: Coding: Fleeting Thoughts

Postby KnightExemplar » Fri Aug 01, 2014 5:02 am UTC

Jplus wrote:
KnightExemplar wrote:Monotone Piecewise Cubic Interpolations

I guess it's friendly to the (flawed) human expectations. But what does it do to the spectrum of the signal?


Good question.

Although most interpolation problems I've come across are all about human expectations. Keyframe interpolation across animation. Be it in video editing, "levels" charts in Gimp / Photoshop, Blender 3d models... I come across splines almost 90%+ of the time in some sort of art program. And every damn time, its a cubic spline. When I make a point a local maximum, I expect it to be a local maximum... not the local maximum to be slightly to the left or right depending on some arbitrary mathematical definition of "smoothness in the 2nd derivative".

Monotone Piecewise Cubic Interpolations are closer to what humans expect when you interpolate human-made data.

EvanED wrote:
Jplus wrote:I feel this can't be stressed enough. Toys are always the best way to learn something, regardless of what it is. Here, have at some wonderful programming toys...
Manufactoria
KOHCTPYKTOP
The Codex of Alchemical Engineering
Minecraft (payware)
Cargo-Bot (iPad only)
I am a fan of SpaceChem. :-)


No Turtle Logo fans?

Seriously though, I learned on Ti-83 Basic (though you youngsters probably use TI-84+ now), writing code that made homework much much easier to solve. After that, I moved on to Robocode competitions.
First Strike +1/+1 and Indestructible.

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 » Fri Aug 01, 2014 5:31 am UTC

My first experience with programing was using AppleScript to cause alarming error messages to pop up on my friends' computers at startup time. (Reformat hard drive? [yes/ok]).
He/Him/His/Alex
God damn these electric sex pants!

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

Re: Coding: Fleeting Thoughts

Postby Xenomortis » Fri Aug 01, 2014 9:43 am UTC

Shellscript is terrible and every time I look at it I want to gouge out my eyes.
Image

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

Re: Coding: Fleeting Thoughts

Postby phlip » Fri Aug 01, 2014 3:24 pm UTC

Xenomortis wrote:Shellscript is terrible and every time I look at it I want to gouge out my eyes.

Whenever I start to feel this way, I open up the one non-trivial CMD script I've ever managed to write for work, and suddenly feel a lot better about my life by comparison.

Code: Select all

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

heatsink
Posts: 86
Joined: Fri Jun 30, 2006 8:58 am UTC

Re: Coding: Fleeting Thoughts

Postby heatsink » Fri Aug 01, 2014 4:06 pm UTC

KnightExemplar wrote:Wait, what about C++0x closures don't match up with the proper definition? C++ closures can capture both by value and by reference, so they're at least as good as Scheme closures.

I think the leaky environment is not the only issue with C++11 closures.

C++11 captures one of the ideas behind closures, which is to support dynamically generated functions. However, it doesn't make dynamically generated functions first-class. Many programming methods involve dynamically choosing which value to use (think of "if" statements and lookup tables). C++11 gives every lambda a different type, which implies that you can't dynamically decide which lambda function to use. More precisely, C++11 lambdas make captured variable environments first-class, but they do not make code first-class. This feels like a weird and clumsy restriction when you're used to first-class functions.

If you want first-class functions, you can use std::function. You still have to think about lifetimes of captured variables, to use casts and wrappers for compatibility with functor-based interfaces, and to make design decisions about the tradeoffs between fast lambdas and slow std::function.

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

Re: Coding: Fleeting Thoughts

Postby Yakk » Fri Aug 01, 2014 4:56 pm UTC

Yes, type-erased function objects are going to be slower than non-type erased function objects. Why would it be worse that they give you the option to use non-type-erased function objects?

std::function is not (fundamentally) any slower than any other "first class function object". C++ just gives you a faster option as well.

C++ object lifetime of automatic storage data is a feature, in that you know when you create the object when the object will be destroyed. Guaranteed. If you do not want to know when an object will be destroyed, you can use free store and smart pointers. (The lack of trace based gc pointer in C++ is a flaw, but the ability to write one via a library is being worked on).

The semantics of references to destroyed storage is also clear: any access causes undefined behavior. Expecting that to work is like expecting to have read/write access to some shared data and complaining that someone else wrote 0 to it.

This does mean that use of variables of automatic storage duration requires you to think about their lifetime and the lifetime of references that capture them. The alternative remains (don't store non-temporary data in there, and capture the smart pointers). The existence of a different option does not rule out the one you want existing.

With auto and make_shared, there isn't even that much code overhead:

Code: Select all

std::function< int() > make_counter( int starting_at ) {
   auto x = std::make_shared<int>(starting_at);
   return [x](){ return (*x)++; }
}

You can go as far as you like, making shared data more of the default and automatic storage less of a default, all the way to never creating data that isn't a shared_ptr in automatic storage, and capturing nothing by reference.
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
Jplus
Posts: 1721
Joined: Wed Apr 21, 2010 12:29 pm UTC
Location: Netherlands

Re: Coding: Fleeting Thoughts

Postby Jplus » Fri Aug 01, 2014 6:35 pm UTC

KnightExemplar wrote:Monotone Piecewise Cubic Interpolations are closer to what humans expect when you interpolate human-made data.

Ah, right, that does make it useful.

No Turtle Logo fans?

Seriously though, I learned on Ti-83 Basic (though you youngsters probably use TI-84+ now), writing code that made homework much much easier to solve. After that, I moved on to Robocode competitions.

I am a fan of Logo, although I have never really used it myself, but I think in some sense it is more "serious" learning material than the games listed previously. I mean, even though it's fun and even child-friendly, it is very explicit about what it means to write a program, in an intellectual (though accessible) way. The games mentioned so far, on the other hand, on the surface are more about immersing yourself in some fantasy situation that happens to involve a little bit of programming. Mind you, that's still a good way to learn it.

I started out programming Basic on a graphing calculator too, but on a Casio.

I would also have mentioned RoboCom, but unfortunately it seems it isn't available anymore.

ahammel wrote:My first experience with programing was using AppleScript to cause alarming error messages to pop up on my friends' computers at startup time. (Reformat hard drive? [yes/ok]).

YMMD

phlip wrote:
Xenomortis wrote:Shellscript is terrible and every time I look at it I want to gouge out my eyes.

Whenever I start to feel this way, I open up the one non-trivial CMD script I've ever managed to write for work, and suddenly feel a lot better about my life by comparison.

Eww. It reminds me of my attempts to write a batch equivalent of the source command.

Edit: forgot the last quote.
Yakk wrote:With auto and make_shared, there isn't even that much code overhead:

Code: Select all

std::function< int() > make_counter( int starting_at ) {
   auto x = std::make_shared<int>(starting_at);
   return [x](){ return (*x)++; }
}

You can go as far as you like, making shared data more of the default and automatic storage less of a default, all the way to never creating data that isn't a shared_ptr in automatic storage, and capturing nothing by reference.

This.
"There are only two hard problems in computer science: cache coherence, naming things, and off-by-one errors." (Phil Karlton and Leon Bambrick)

coding and xkcd combined

(Julian/Julian's)

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

Re: Coding: Fleeting Thoughts

Postby Xeio » Fri Aug 01, 2014 9:08 pm UTC

Code: Select all

Exception ...
at System.Data.SqlClient.SqlTransaction.ZombieCheck()
Uh oh.

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

Re: Coding: Fleeting Thoughts

Postby Xenomortis » Fri Aug 01, 2014 9:10 pm UTC

Time to grab the shotgun?
Image

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

Re: Coding: Fleeting Thoughts

Postby Thesh » Sat Aug 02, 2014 6:55 am UTC

I think there needs to be an intermediate between returning error codes and exception handling. I'm thinking something like this:

Code: Select all

int divide(int x, int y) except enum math_error
{
   if (y == 0)
   {
      except DIVIDE_BY_ZERO;
   }
   else
   {
      return x/y;
   }
}

int main()
{
   int a = 5, b = 4, c;

   call divide(x, y);
   success(c) //optionally, variable can be declared here, or it can be left empty if you don't care about the return
   {
      printf("%d\n", c);
      return 0;
   }
   failure(enum math_error e) //same as above, variable can be declared above, or left empty
   {
      printf("Something's fucked.\n")
      return -1;
   }
   //success and failure must be immediately preceded by call statement failure or success, respectively.
   //if a function defines an exception handler, it must be executed using call
}


On top of that, I would still like to see a finally block, but one that executes as long as code reaches the block immediately proceeding it, regardless of what it does.

Code: Select all


int main()
{
   int a = 5, b = 4;
   int *c = (int *)malloc(sizeof(int));

   {
      call divide(x, y);
      success(*c)
      {
         printf("%d\n", *c);
         return 0;
      }
      failure(enum math_error e)
      {
         printf("Something's fucked.\n")
         return -1;
      }
   }
   finally
   {
      free(c);
   }
   
}



The reason I like that syntax is because return and except, and success and failure are all the same number of characters.
Summum ius, summa iniuria.

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

Re: Coding: Fleeting Thoughts

Postby Yakk » Sat Aug 02, 2014 9:21 am UTC

Bah, missed a page of discussion before my last post, sorry.

...

Except for return, we csn do that in a library solution thresh. With std::expected or optional, and two lambdas for the bodies.

I could imwgine syntax like:

Code: Select all

call(func(a,b,c),
[&](int result){
    // success

},[&](err_code err){
    // failure
});

You just cannot return -1; from the failure branch. You could merge the return values of each branch, and have `call` return a tagged union/common type, then ask the hosting function to re-return...

We are >< close to full library flow control: and I am unsure if takimg the last step (blocks that can return from outer blocks) is worth it/will happen.
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.

korona
Posts: 495
Joined: Sun Jul 04, 2010 8:40 pm UTC

Re: Coding: Fleeting Thoughts

Postby korona » Sat Aug 02, 2014 10:07 am UTC

heatsink wrote:If you want first-class functions, you can use std::function. You still have to think about lifetimes of captured variables, to use casts and wrappers for compatibility with functor-based interfaces, and to make design decisions about the tradeoffs between fast lambdas and slow std::function.

Sure you have to make trade offs between fast lambdas and slow std::function. But the great thing is that C++ gives you this choice. In JavaScript / Python / whatever language with closures you're thinking about you always implicitly use a slow construct. As the greatest overhead of std::function comes from the heap allocation that is required to store the functor (i.e. captured values) this cost is somewhat reduced in garbage collected languages where an allocation is done by simply increasing a pointer and where copying the function object does not involve copying this memory region because it is garbage collected.

In my experience it is much better to mange C++ closures yourself than to use lambda to std::function conversions. Create a class for the values you want to capture, allocate an object of this call on the heap and then just capture this object by reference. That way std::function's small functor optimization will trigger and you can avoid lots of new/copy/delete operations when you pass std::function objects around.

User avatar
mosgi
Posts: 46
Joined: Thu Jul 17, 2014 8:19 pm UTC
Location: Somewhere in your past light cone

Re: Coding: Fleeting Thoughts

Postby mosgi » Sat Aug 02, 2014 12:58 pm UTC

Thesh: I quite like Haskell's way of dealing with the eternal problem of error codes vs. exceptions, so I've made a fairly straight translation of your first example:

Code: Select all

import Control.Monad.Except
import System.Exit

data MathError = DIVIDE_BY_ZERO deriving Show

divide :: Int -> Int -> Except MathError Int
divide _ 0 = throwError DIVIDE_BY_ZERO
divide x y = return $ x `div` y

main :: IO ()
main = do
    let a = 5
        b = 4
    case runExcept $ divide a b of
        Right c -> do
            print c
            exitWith ExitSuccess
        Left e -> do
            putStrLn "Something's fucked."
            exitWith $ ExitFailure (-1)


Though it does raise the question: Isn't -1 an invalid exit code? I thought you were only meant to return positive values, with negative values being for signals.

Either way, this doesn't show off what I like about Haskell's way of doing this. The thing I really like about it is that you can mix and match the two behaviours. As a simple example, say we want a function which takes arguments w,x,y,z and returns (w/x) + (y/z). Well, there are two ways of writing it:

Code: Select all

-- Exception-like behaviour
testExcept :: Int -> Int -> Int -> Int -> Except MathError Int
testExcept w x y z = do
    a <- divide w x
    b <- divide y z
    return $ a + b
-- Alternately, as a one liner:
-- testExcept w x y z = liftM2 (+) (divide w x) (divide y z)

-- Error-code-like behaviour
testCode :: Int -> Int -> Int -> Int -> Except MathError Int
testCode w x y z =
    case runExcept $ divide w x of
        Right a -> case runExcept $ divide y z of
            Right b -> return $ a + b
            Left e -> throwError e
        Left e -> throwError e


The first one is obviously better if you just want to propagate errors, whereas the latter is better if you want to catch the errors and do something with them. There are also a bunch more standard functions which can be used to make the first kind of code look even more like standard "exception-ignoring" code.
(they pronouns please)

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

Re: Coding: Fleeting Thoughts

Postby Thesh » Sat Aug 02, 2014 4:25 pm UTC

mosgi wrote:Though it does raise the question: Isn't -1 an invalid exit code? I thought you were only meant to return positive values, with negative values being for signals.

Probably shouldn't use it, no, but there are no invalid exit codes in C (provided it is in the range of interest) - the OS is a different story (it will work fine on Windows, but Linux and Unix are trapped in the 80s).

Haskell error handling is interesting, but I'll have to look at it when I didn't just wake up.
Summum ius, summa iniuria.

KnightExemplar
Posts: 5494
Joined: Sun Dec 26, 2010 1:58 pm UTC

Re: Coding: Fleeting Thoughts

Postby KnightExemplar » Sun Aug 03, 2014 2:59 pm UTC

Thesh wrote:I think there needs to be an intermediate between returning error codes and exception handling.


The real problem is that "throw" is crappy in C++, and compilers aren't good enough at catching certain bugs.

Technically speaking,

Code: Select all

int f() throw (ExceptionTypeA){
}


The C++ "throws" in this case is supposed to exhaustively list all possible exceptions. (The default "int f()" function can throw any exception. Adding "throws" restricts the list). So, if you want an "exceptionless" function, then you want "int g() throw ()". At least... in theory.

Alas... things are more complicated than that, and C++0x wasn't able to address it. So its now standard C++ coding convention to just ignore exception specifiers, as they don't work the way anyone expects them to.
First Strike +1/+1 and Indestructible.

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

Re: Coding: Fleeting Thoughts

Postby Yakk » Tue Aug 05, 2014 5:06 pm UTC

noexecpt(expression) handles the most common case (saying I do not throw).

There is a proposal to add `std::except< T, Error >` to C++1y. In functions where I do not care about the error, I use `optional<T>` and return `nullopt` when the function failed, and it works reasonably well.
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
Izawwlgood
WINNING
Posts: 18686
Joined: Mon Nov 19, 2007 3:55 pm UTC
Location: There may be lovelier lovelies...

Re: Coding: Fleeting Thoughts

Postby Izawwlgood » Tue Aug 05, 2014 7:13 pm UTC

I am by no means even a mediocre coder, but lately I've been driven nuts by a group of gamers complaining about an extremely broken script they run in a game we all play. The script they use is approximately 1,000 pages of bloated, convoluted text, that does a terrible job and rarely works. My script is approximately 1,000 LINES of text, is modular and easily adjustable, and doesn't suffer from any of the issues of theirs.

I keep wanting to just shake them and be like "JUST USE MY GODDAMN CODE".

Ever experience that? The desire to push someone aside and be like 'Nonono, get off, you're done, let me do this the right way'.
... with gigantic melancholies and gigantic mirth, to tread the jeweled thrones of the Earth under his sandalled feet.

User avatar
mosgi
Posts: 46
Joined: Thu Jul 17, 2014 8:19 pm UTC
Location: Somewhere in your past light cone

Re: Coding: Fleeting Thoughts

Postby mosgi » Tue Aug 05, 2014 7:28 pm UTC

Izawwlgood wrote:Ever experience that? The desire to push someone aside and be like 'Nonono, get off, you're done, let me do this the right way'.

Oh so very very much. In particular, one of the programs I'm working on as part of my internship. To be fair, the way it's designed it isn't necessarily bad per se, it's just that it's less than ideal and has ended up a bit of a pain to maintain. I've resorted to making ad-hoc changes for the moment, which really doesn't help, but have promised myself that I'll tidy it up properly later on (and I've even budgeted time for it!). A full redesign is out of the question though.
(they pronouns please)

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

Re: Coding: Fleeting Thoughts

Postby Thesh » Tue Aug 05, 2014 7:38 pm UTC

Well, every single company I have worked for I had expressed a desire to rewrite legacy systems from scratch. There is usually a belief that if it isn't broken, don't fix it, and if it is broken, then just fix it. There are two things at play, one is cost - a quick fix is quick is less costly (although quick fixes tend to become permanent code), and two the more that you change a system, the more likely you are to have new issues. When you have legacy systems, you see a lot of "Why do we do this?" and it tends to be some odd business case that everyone forgot about and you can't change. If you can get past that, usually cleanup is the best course, if your problem truly is that you have a messy, unmaintainable code base.

Not sure if any of this applies to your current situation.
Summum ius, summa iniuria.

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

Re: Coding: Fleeting Thoughts

Postby Yakk » Tue Aug 05, 2014 7:54 pm UTC

*nod*. Do not assume that everyone who maintained or wrote a legacy system was an idiot.

Even if they where, you are going to have systems on top of the legacy system that rely on quirks in the legacy system design.

Replacing legacy systems is both expensive and dangerous. Even if you have a simple system that does 80%-90% of what the legacy system did "but much simpler". The last 20% will take up 80% of the work, and this is recursively true.

Which means it takes basically an infinite amount of work to get to 100%.

It is possible to replace chunks of a legacy system often, but doing it reliably usually involves first factoring the legacy system so that a part can be cleanly removed and replaced. Then ensuring, proving and testing that the swap out of the legacy system with a new system was safe. Then repeating.

If the legacy system is overly complex and difficult to understand, this isn't possible. So any fix has to approach it as a disruption: your goal is to make a system that is so much cheaper to run (in whatever dimension), it destroys the business case for the old system.
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
mosgi
Posts: 46
Joined: Thu Jul 17, 2014 8:19 pm UTC
Location: Somewhere in your past light cone

Re: Coding: Fleeting Thoughts

Postby mosgi » Tue Aug 05, 2014 8:08 pm UTC

Thesh and Yakk: Oh, I've read far too many accounts of people trying to "fix" legacy systems to try that ;) Though thanks for the reminder, it's a lesson worth repeating!

In this case it's a little different. I'm having to add features in order to support the work I'm supposed to be doing, and the part of the code I'm going to be tidying up is entirely my own additions. Essentially, what I've been adding is the smallest amount possible to get by (so I can focus on other things), but with a bit of work it should be possible to bring it more in line with the current style of the code. It will involve some minor refactoring, but nothing too heavy. And the other thing I'm working on provides ample tests to make sure it does the right thing (it's an assembler, I can just diff the output against a known-working copy of my code).

That said, if I were doing a personal project on this system I really would redo the assembler from the ground up. But I realise that it would take far too much time and effort to be worth doing so for this internship, and once it's fixed it should "just work". Hopefully.
(they pronouns please)

korona
Posts: 495
Joined: Sun Jul 04, 2010 8:40 pm UTC

Re: Coding: Fleeting Thoughts

Postby korona » Tue Aug 05, 2014 9:23 pm UTC

Yakk wrote:noexecpt(expression) handles the most common case (saying I do not throw).

There is a proposal to add `std::except< T, Error >` to C++1y. In functions where I do not care about the error, I use `optional<T>` and return `nullopt` when the function failed, and it works reasonably well.

I've googled for this proposal and it seems std::except has not been submitted to the standards committee or boost yet. Is std::optional already available (outside of boost) in a mainstream compiler like g++, Visual C++ or clang?

I agree with your points about legacy systems. Programmers always want to start from scratch and "do it right" this time. But after enough hours have been put into the code base many ugly hacks to get around edge cases, operating systems / library limitations and so on show up again. Cleaning up code is almost always better than rewriting it from scratch, unless the code in question is just a small snippet.

KnightExemplar
Posts: 5494
Joined: Sun Dec 26, 2010 1:58 pm UTC

Re: Coding: Fleeting Thoughts

Postby KnightExemplar » Tue Aug 05, 2014 11:00 pm UTC

Yakk wrote:noexecpt(expression) handles the most common case (saying I do not throw).


Still has the same problem however. If a function declared noexcept ever does throw an exception... the program calls std::terminate.

IE: Your program is murdered. You had no chance to save your user's data, you had no chance to create a auto-save restore point. Your program is executed on the spot.

What we _actually_ want is a compiler-check to ensure that noexcept functions only call other noexcept functions... or something along the lines of const-correctness. As much of a pain-in-the-ass as const-correctness is... it actually works for its intended purpose.

noexcept does _NOT_ provide a compile-time check, it only provides a (wtf???) runtime check of exceptions.
First Strike +1/+1 and Indestructible.

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

Re: Coding: Fleeting Thoughts

Postby Thesh » Tue Aug 05, 2014 11:08 pm UTC

The problem with guaranteeing no exceptions occur at compile time is that any heap allocation would be disallowed which is extremely limiting.
Summum ius, summa iniuria.

KnightExemplar
Posts: 5494
Joined: Sun Dec 26, 2010 1:58 pm UTC

Re: Coding: Fleeting Thoughts

Postby KnightExemplar » Tue Aug 05, 2014 11:26 pm UTC

Thesh wrote:The problem with guaranteeing no exceptions occur at compile time is that any heap allocation would be disallowed which is extremely limiting.


Its better for the program to fail to compile, than for the program to call std::terminate in some crazy corner-case.

Consider this: any "new" that fails in a noexcept function will cause std::terminate and murder your program (and definitely murder at least some of your user's data without any chance at recovery). A compile-time error restricting you to not use "new" within "noexcept" functions is significantly better than the current status-quo.
First Strike +1/+1 and Indestructible.

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

Re: Coding: Fleeting Thoughts

Postby phlip » Tue Aug 05, 2014 11:33 pm UTC

And anyway, isn't there a "nothrow" version of new that returns null on failure, instead of throwing an exception? I thought that was a thing that existed...

Code: Select all

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

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

Re: Coding: Fleeting Thoughts

Postby Thesh » Tue Aug 05, 2014 11:42 pm UTC

Actually, now that I think about it, even if you call a function that can throw an error, if it is wrapped in a try/catch you can guarantee that it doesn't result in the calling function throwing an exception, so that could be doable. Especially if you have compiler enforced exception specifications.

I still like my idea.
Summum ius, summa iniuria.

User avatar
Jplus
Posts: 1721
Joined: Wed Apr 21, 2010 12:29 pm UTC
Location: Netherlands

Re: Coding: Fleeting Thoughts

Postby Jplus » Tue Aug 05, 2014 11:59 pm UTC

phlip wrote:And anyway, isn't there a "nothrow" version of new that returns null on failure, instead of throwing an exception? I thought that was a thing that existed...

Yes.
"There are only two hard problems in computer science: cache coherence, naming things, and off-by-one errors." (Phil Karlton and Leon Bambrick)

coding and xkcd combined

(Julian/Julian's)

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

Re: Coding: Fleeting Thoughts

Postby phlip » Wed Aug 06, 2014 12:38 am UTC

The problem with checked exceptions is that there are exceptions that are declared, but in context can never be thrown... usually exceptions that indicate programmer error, rather than a bad state... This tends to get tedious, and writing this sort of code gets old quickly:

Code: Select all

String str = null;
try {
  str = new String(byteArr, "UTF-8");
} except (UnsupportedEncodingException e) {
  log.error("Somehow UTF-8 doesn't exist any more...", e);
}
The exception has to exist, and new String(byte[],String) has to be able to throw it, because you can pass in arbitrary strings that aren't actually the names of charsets. But in this case we aren't doing that... but we still need to catch the exception. In the most extreme, you could end up with every division needing to have a try/catch to catch a division-by-zero exception, even if the divisor is guaranteed to be nonzero in a particular case. Some of these you can eliminate with optimiser tricks (if the divisor is a nonzero constant, then no exception can be thrown) but it would be a challenge to make that universal.

So even with checked exceptions, you really want to have a mechanism like Java's RuntimeException that lets you have certain exceptions that are more "if this happens in dev code, you want to know about it, but in bug-free code it should never happen, regardless of state". The problem is that you can't necessarily tell when you're writing a piece of code whether it should throw a checked exception or not... is UnsupportedEncodingException a state error or a programmer error? Well that depends on whether it's coming from a user, or whether it's a hardcoded constant with a typo in it. It depends on context in the calling code... so either way, it's going to be wrong sometimes.

And once you have a RuntimeException-style mechanism for exempting yourself from the must-be-caught system, it will be abused... I don't think there's anyone who's worked on a Java project and hasn't made some exception extend RuntimeException just because they couldn't be bothered adding "throws" declarations to their functions... and once it's done, it's hard to undo, as you then need to go through a lot of functions and add the appropriate declarations. It's as bad as retrofitting a C++ program to turn a "char *" to a "const char *" in some high-level function... it requires changing an ungodly number of things.

And it's not just the end developers... once you have unchecked exceptions, they're there to be abused by anyone. In the extreme case, it's essentially impossible to write a noexcept function in Python, because every single line could potentially throw KeyboardInterrupt and there isn't a damn thing you can do about it.

Code: Select all

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

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

Re: Coding: Fleeting Thoughts

Postby EvanED » Wed Aug 06, 2014 2:31 am UTC

Basically, exception specifications are like exceptions: they are simultaneously wonderful to have and also an incredible pain in the ass at the same time.

Or said another way, the only thing I hate more than exceptions is not having exceptions. :-) (Though maybe for exception specifications it would be "the only thing I hate more than not having exception specifications is exception specifications...")

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

Re: Coding: Fleeting Thoughts

Postby Yakk » Wed Aug 06, 2014 1:37 pm UTC

korona wrote:I've googled for this proposal and it seems std::except has not been submitted to the standards committee or boost yet.

That is what I get for reading the standards proposals usenet group.
Is std::optional already available (outside of boost) in a mainstream compiler like g++, Visual C++ or clang?

I don't know -- I just rolled my own and started using it.
I agree with your points about legacy systems. Programmers always want to start from scratch and "do it right" this time. But after enough hours have been put into the code base many ugly hacks to get around edge cases, operating systems / library limitations and so on show up again. Cleaning up code is almost always better than rewriting it from scratch, unless the code in question is just a small snippet.
Really, you clean it up until you have small snippets you can rewrite, and then rewrite those snippets.

Now, disruption is always an option. But it is disruption, not a rewrite. If you have some image filter that you want to write better, it is far easier to write a new image filter that you hope will "out-compete" the old filter than it is to actually replace functionality for functionality the old filter in a "rewrite". Same thing for a mail client.

The new version needs to have some kick ass functionality (efficiency, features, can run on an OS published this millennia, whatever) that make dropping the old one worthwhile to win in such a competition, because you will be missing some functionality from the old version.
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.


Return to “Coding”

Who is online

Users browsing this forum: No registered users and 4 guests