I can’t help but feel that this “method” requires a certain type of ego. I don’t develop and release software to have something “succeed,” such that I can gain some notoriety, or street cred. I develop and release software to scratch my own itch, solve my own problems, and release it in the hopes that it’ll be useful to someone else. I share because I believe sharing is the right thing to do.
Do I have as big a following as fogus? No. So, maybe it’s different somehow. Maybe there are expectations on him that don’t exist for me–that’s probably the case. But, that still wouldn’t change my behavior. I still wouldn’t keep things to myself until such time as it’s ready. That’s selfish in my opinion.
People are ridiculous and expect free work to be done, of course. “Fix my bug! You’re obligated to do so because you open sourced it!” No. No, I’m not obligated. You can fix it yourself (or pay someone else to do so) if I don’t have interest in doing so, but a “thank you” for the effort I put into it so far would be nice. That’s why I released it under a permissive license to begin with.
I still wouldn’t keep things to myself until such time as it’s ready. That’s selfish in my opinion.
Now you see, I don’t see it that way. What makes me feel selfish is when people use software that I’ve created haphazardly for projects that they depend on for real results and I’m not around to help them out. Should they have thought twice before including it? Probably. That doesn’t make me feel any less like a delinquent maintainer however. You say that holding back code is selfish and ego-centric, but I see it exactly the opposite. I highly doubt that most of what I create is worth a hill of beans to anyone, but occasionally I might stumble onto something of real value that I an likewise excited about. I think Christopher Hitchens had something to say about this:
Everybody does have a book in them, but in most cases that’s where it should stay.
I understand your point of view, I just don’t agree with it. :)
Everybody does have a book in them, but in most cases that’s where it should stay.
This is pretty short sighted, don’t you think? It also doesn’t mention how one knows that it should stay in them. If Mark Twain didn’t publish his short stories, because someone told him to “keep it to yourself,” we’d probably never have been introduced to Tom and Huck later.
You could of course argue that Twain wrote thousands of pages of rubbish before publishing anything “worthwhile,” but whose to say it wouldn’t have inspired other authors, or formed the basis for some new radical innovation in literary work?
The problem with keeping things to yourself is simply that there’s never a chance for anyone else to benefit from it. There’s never a chance for someone else to be inspired by what you’ve created, even if it’s insignificant to you.
Also, while probably not directly related (I don’t know the full story of what he published vs. didn’t), Ramanujan’s story. He was discovered quickly by researchers, but what if he hadn’t been?
Being vaguely familiar with Twain’s life, I think it’s extremely unlikely that he would have listened to anyone telling him to keep it to himself. In fact, I imagine such requests were a constant refrain for him. :)
I do actually think the choice of how much to publish is very personal. I think the majority of fun projects I do have very little value to anyone else (other than recruiters who want to determine that, yep, I’m one of those people with several dozen GitHub repositories, most of which have 100 lines of code). But I’m definitely not going to adopt a philosophy that says I have to focus on stuff that’s useful to others to the exclusion of stuff I enjoy - and that is pretty much what I understand 100:10:1 to be about.
That’s the main point for me, but as side points… I don’t think releasing code creates an obligation, but I do weigh whether other people are going to feel that it does. I also weigh whether the code might be a useful example for someone, regardless of whether it works. And at least part of my motivation for open-sourcing things is selfish - I want feedback on them! In general, everyone has their own reasons, which are pretty diverse.
I do actually think the choice of how much to publish is very personal.
Absolutely agreed! I don’t think anyone should change their philosophy just because I (or anyone else) said so. One needs to internalize their own beliefs, and come to their own conclusions. Obviously, you may do this by reflecting on my, or someone else’s beliefs, though.
And at least part of my motivation for open-sourcing things is selfish - I want feedback on them!
Hack && Tell was started for exactly this reason – feedback, among other things, of course. But, I can’t tell you how many times I’ve seen (at Hack && Tell or otherwise), 100 line “hacks” with no “value,” that inspired me to create something else that was 150 lines with no “value.”
It’s only a matter of time before that 150 line hack leads to 20,000 lines of pure world changing innovation.
In its history, there were 2, run by separate people, but, I think organizer interest waned and it fizzled out.
I’m no longer involved (I started it in NYC, but recently moved to San Diego), but left it with a fantastic set of organizers (one of which has been involved since the beginning) who are trying to push it forward and make it easy for new chapters to start. It is surprising to me that a Bay Area chapter never took off, but having been the organizer (and also having worked at Meetup), I realize that it probably has less to do about “interest” and more about getting the right person(s) involved in stepping up to organize.
That’s why I released it under a permissive license to begin with.
I release stuff under the GPL and I also don’t promise to support it or handle anyone’s bug reports or feature requests. Not my problem, take it or leave it. I need to keep my sanity.
In the highly unlikely case that starting from my stuff they create and disseminate non-free stuff and I find out about it, I have the option to do something, but otherwise it’s just about the same as a permissive license.
Anyways point being is that releasing software under a permissive vs copyleft license has no bearing on our obligations towards others. It’s very important to realise that we have no obligations, because otherwise burnout can settle in, due to all of these freeloaders asking for something for nothing. I have seen it happen multiple times. You have to be zen.
I release stuff under the GPL and I also don’t promise to support it or handle anyone’s bug reports or feature requests. Not my problem, take it or leave it. I need to keep my sanity.
I’ve tried that. It didn’t work for me. 100:10:1 does.
Only two at the moment:
Tools of Thought: The History and Future of Mind-Expanding Technology by Howard Rheingold is basically a book about (a portion of) what goes through Alan Kay’s head.
Game & Puzzle Design, vol. 1, no. 1 edited by Cameron Browne.
This always bothered me about haskell. Why is it it so hard to read a line from a file? I understand that because of jumping through all of these hula hoops we end up in situations where the compiler can suddenly magically do very cool things, but it feels like so much effort. I’m sure it’s effortless after you’ve internalized the state monad and the io monad and the writer monad and the reader monad, but until then, it still feels like a pain.
This has nothing to do with reading a file. There is nothing about the IO monad in the article.
Reading a file is not hard:
main = do
content <- readFile "/tmp/test.txt"
let firstLine = head (lines content)
putStrLn firstLine
Done.
Where was the effort?
Since my above Haskell is actually async, let’s talk about real effort:
var fs = require('fs');
fs.readFile('/tmp/test.txt', 'utf8', function(err, content) {
var firstLine;
if(err)
return console.error('Error loading file');
firstLine = content.split(/\n/)[0];
console.log(firstLine);
});
If I didn’t want to putStrLen at the end, but instead wanted to do something else, would it be so easy? I might be misunderstanding, but my impression is that putStrLn eases my way here because putStrLen wraps firstLine in the IO monad for me.
I think you might be misunderstanding. The putStrLn function takes a String and returns an IO action. What other than printing to the screen would you like to do? The last line could be anything!
main = do
content <- readFile "/tmp/test.txt"
let firstLine = head (lines content)
name <- getName
printMessage name firstLine
getName = do
putStr "What is your name? "
readLn
printMessage name line =
putStrLn ("You are " ++ name ++ " and the first line is " ++ line)
I must be misunderstanding the type constraints. My impression is that I need the do loop to end with an IO. What if I wanted to parse the text file and return the sum of a bunch of numbers in the text file? If I could figure out how to wrap the number in an IO monad again, that would make it typecheck.
I could just be badly misunderstanding do loops.
Gotcha. I guess I just had too much trouble with the haskell docs. My impression was that I could find everything I needed to know about IO here, but clearly I should have used my google-fu and ended up here. Thanks for the clarification!
That definitely makes the IO monad easier to work with, although it still seems onerous to me. I think I’ll have to force myself to do more with it in order to internalize how it works before it seems simple.
It’s not hard to read lines from a file as Brian showed. Have you used Haskell before or do you just think that it’s hard to do trivial tasks like that?
My main experience with the IO monad was trying to parse commandline options, which I found deeply frustrating. Definitely part of the problem was my inexperience with haskell, since before this I had only done trivial work in it before. However, it seems unreasonable to me that it should be so complicated.
More precisely, I like that in Scala I can just look up io.Source.fromFile(“filename”).getLines (or something similar) and it hands me back an iterator, instead of an IO iterator which I have to be super careful with, especially since it isn’t clear to me how to unwrap an IO a la
val x = unwrap IO(lines)
edit: I am aware that my example of having a hard time with the IO monad is godawful haskell.
You can’t completely unwrap IO, that’s the point. You always want to wrap it back up with map or flatMap/bind/chain. That’s exactly what do-notation does:
main = do
content <- readFile "/tmp/test.txt"
-- "content" as being unwrapped
let x = lines content
-- wrap it back up with "print"
print x
I am having trouble understanding how I do this:
read data from a file
get out of io land with that data
manipulate that data
later, output the result of manipulating the data.
The impression I have now is that it is illegal to leave IO land with that data, unless it is safely wrapped in an IO. If I wanted to do something like this, instead the right way would be to say something along the lines of
let x = read data
let y = map x manipulate
-- I don't know map syntax in haskell
do
manipulated <- y
putStrLn manipulated
it seems like a pain to have to add an extra level of mapping every time I want to manipulate something that came from outside. I have heard that this is to protect us from the outside world since it is impure, but I suppose I just haven’t internalized it.
The above example does almost the 4 things you listed. Let’s go line by line:
main = do
read data from a file
content <- readFile "/tmp/test.txt"
Now here’s the thing – content is not an IO value but it’s also not “out of IO land” because it can’t escape (the whole do expression must return an IO).
manipulate that data
let x = lines content
later, output the result of manipulating the data.
print x
I understood that part. What I didn’t understand how to do was how to carry around the IO in a subsequent expression.
Maybe this will help clarify things:
import Data.Char
shout :: String -> String
shout line = map toUpper line
getLines :: String -> IO [String]
getLines filename =
do content <- readFile filename
let ls = lines content
let shoutyLines = map shout ls
return shoutyLines
main :: IO ()
main =
do shoutyLines <- getLines "example.in"
let joinedLines = unlines shoutyLines
putStrLn joinedLines
getLines :: String -> IO [String]
getLines takes in a String and, if it is ever run, does some IO and
returns a list of Strings. In this case, if it is run, it reads all
the lines from a file into a list of Strings, converts each of those
strings to uppercase and returns (lifts it into a Monad context) the
new list.
By the way, the above code could also be written as (and it actually gets expanded into something very similar since do notation is just syntactic sugar):
import Data.Char
shout :: String -> String
shout line = map toUpper line
getLines :: String -> IO [String]
getLines filename =
readFile filename >>= \content ->
return $ map shout $ lines content
main :: IO ()
main =
getLines "example.in" >>= \shoutyLines ->
putStrLn $ unlines shoutyLines
Ugh. I don’t know. Looks like they will have the opportunity to learn… a vast amount of stuff. I feel like if they set their goals to be that broad, they are setting themselves up for some disappointment. I don’t want them to be disappointed at osdev. It’s very rewarding if you can establish some scope eventually. I know that @fogus certainly was active in the osdev community, so maybe you’d agree?
I mean, I feel bad! Looks like they want to write a new OS layer, not a kernel, but still want to know what the kernely things are like. I say do both, independently. Write a kernel, respect it, throw it away, grab an existing kernel, write a userspace, respect that, throw most away, write up postmortem. That would be far better!
Writing all software from scratch is like riding a unicycle over a minefield.
Jeez. For god’s sake, don’t use visual studio for your kernel development environment. Or windows for that matter. There is a reason why nobody does that. You’re going to hit the point where you’ll want passthrough-io and then be really sad that windows doesn’t really care about you. :D Don’t use the JamesM tutorials, they are absolute crap. Use xv6 instead and program in a unix/linux environment.
Also, I relate to the stupid x86 backwards compatibility all the way up the colon thing Intel does. But… it only takes about a millisecond or something stupidly small to switch from real to protected to long mode. Memory holes? Described by BIOS well enough (although if you are getting rid of the bootloader, you’ll have all kinds of fun with that you could otherwise avoid.) Basically, I would never recommend writing a bootloader /and/ a kernel. Not much to learn that doesn’t overlap, really, and it’s really really not fun. :P
Also, yes, I agree. Screw POSIX. I could care less about the names of functions, but it has serious flaws that mean it is basically not fully supported anywhere. For instance, fork() is dumb. I’m hoping this experience teaches gusC here why that is the case. :)
I don’t want them to be disappointed at osdev.
OSDev is a harsh mistress. There are many who enter and view few who leave with more than a bootloader. I encourage anyone to try, but you have to really really like the guts of a system — and like real guts, modern hardware stinks to its very core.
I’m a bit confused because (based on the title and opening section) I thought this was going to be about how to deal with the FOSS community and how to choose what to release. Instead it turned out to be a framework for generating new ideas, new projects.
I enjoyed the piece regardless!
It was exactly about how I deal with the FOSS community and how I choose what to release. It is in no way prescriptive.