(Untitled)
Man, sometimes Haskell is hard to wrap your head around. I figured I’d spend some time fiddling with it in before I try to do something stupid. Since I’m going to write an indexer, I’m going to want to work with binary file formats, which means marshaling data to and fro. I read the first half of this article, and figure the way I’d be most comfortable manipulating binary data would be to use the C approach as much as possible — allocate an array, read into that array, and then use the data.
And doing just that has taken a good hour to produce the following code –
ghci> import IO ghci> h <- openFile "data" ReadMode ghci> import Foreign ghci> a <- mallocArray 20 :: IO (Ptr Int) ghci> import System.IO ghci> hGetBuf h a 20 ghci> import Foreign.Marshal.Array ghci> let b = advancePtr a 1 ghci> n' <- peekArray 1 a ghci> let n = n' !! 0 ghci> l <- peekArray n b [100,200,300,400] ghci> free a
And the code which actually populates the file read in (I wrote a 4-line C program to bootstrap) –
ghci> h <- openFile "data" WriteMode ghci> b <- mallocArray 20 :: IO (Ptr Int) ghci> pokeArray b [4,100,200,300,400] ghci> hPutBuf h b 20 ghci> hClose h ghci> free b
God that was a bitch to figure out, especially the part where you have to add a type signature to the call to mallocArray (which makes a lot more sense now). Fuuuuuuck I’m almost out of beer.
2 commentsJava RAAAAAGGGEEE
So I’m at work working puttering around with WSDL4J, and I’ve got a list of WSDL Parts that I want to map to just their types. Unfortunately, Java doesn’t have a Map.map function, so I figure “why the hell not add one in”. This, as it turns out, is not a good idea.
Anyway, I :sp‘d open a new package, lambda, and started typing. We want a map function which takes a java.util.Map and a lambda (ie, anonymous inner class). First we need to define an interface for the anonymous inner class to implement –
public interface IMapping {
public Object eval( Object o );
}
Then we can define the actual operation –
public class Lambda {
public Map map( Map m, IMapping mobj ) {
if ( m == null ) return null;
Map ret = new Map();
for ( Iterator i = m.entrySet().iterator(); i.hasNext(); ) {
Map.Entry ent = i.next();
ret.put( ent.getKey(), mobj.eval( ent.getValue() );
}
return ret;
}
};
And that’s all fine and dandy. Then I realized that, hey, I actually need to map a java.util.List, not an associative array. I quickly type up the following –
public List map( List l, IMapping mobj ) {
if ( l == null ) return null;
List ret = new List();
for ( Iterator i = l.iterator(); i.hasNext(); ) {
ret.add( mobj( i.next() ) );
}
return ret;
}
When I realize, hey, this is exactly the same as the map function for java.util.Map. So, like any good any-language-but-Java programmer I start refactoring the common code into a more generic, internal implementation. Logically, between containers, the only difference should be how to obtain the iterator, an extra mapping transformation (to accommodate java.util.Map‘s Map.Entry semantics), and a possibly a third lambda which defines how the object gets inserted (realistically, all lists and maps and things should inherit from java.util.Collection and just implement it’s interface). Anyway, I quickly code this implementation up –
private interface ICollectionWrapper {
public Iterator iterator( Collection col );
public void insert( Collection col, Object o );
}
private Object _map( Collection col, IMapping mobj, ICollectionWrapper colwrap ) {
if ( col == null ) return null;
Collection ret = new col.class;
for ( Iterator i = colwrap.iterator( col ); i.hasNext(); ) {
mins.insert( col, mobj.eval( i.next() ) );
}
return ret;
}
So now, for each collection class we want to map, we just have to provide a wrapped IMapping lambda (passed to _map as mobj), and a collection wrapper for strange classes. I set out to change my java.util.Map mapper first:
public Map map( Map m, IMapping mobj ) {
return _map( m,
new IMapping() {
public Object eval( Object o ) {
return ( (Map.Entry) o ).clone() /* ! */
.setValue( mobj( ( (Map.Entry) o ).getValue() ) );
}
},
new ICollectionWrapper() {
public Iterator iterator( Collection col ) {
return ( (Map) col ).entrySet().iterator();
}
public void insert( Collection col, Object o ) {
Map.Entry(
Then I stopped.
This refactoring, which was designed to reduce code duplication, has actually made the code waaay fucking more verbose (because Java’s lambda support is absolute shit). Additionally, I’m not even sure the marked line (/* ! */) is even valid — Java’s anonymous inner classes aren’t actually closures, and don’t actually close on the parent environment — so mobj is probably inaccessible.
The language is so fucking terrible that there’s no real point in even trying to make the code clean. I’ll just add in an extra loop (tripling the amount of code in the actual function that I’m working on) just to perform a trivial mapping. Thanks, Java.
I hate you.
No comments
