lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


It was thus said that the Great Andrew Starks once stated:
> On Thursday, May 1, 2014, Thiago L. <fakedme@gmail.com> wrote:
> 
> > NIL_VALUE = {}
> > softmt = { __index = function(t,k) if rawget(t,k) == nil then return
> > NIL_VALUE else return rawget(t,k) end end }
> > setmetatable(NIL_VALUE,softmt)
> >
> > softtable = {}
> > setmetatable(softtable,softmt)
> >
> > val = softtable.some.invalid.key
> > if val == NIL_VALUE then return "it works!" end
> >
> > Best part? If you don't have a __metatable protected metatable:
> >
> > oldmt = getmetatable(t)
> > setmetatable(t,softmt)
> > val = t.insert.some.long.chain.here
> > if val == NIL_VALUE then val = nil end
> > setmetatable(t,oldmt)
> > -- etc
> >
> > While it's not as nice as Groovy[1] it does the job just fine...
> >
> > [1] http://groovy.codehaus.org/Null+Object+Pattern
>
> The thing is, this hack works with every table in existence, not just ones
> that don't have an __index method that is available for override.
> 
> The trouble(?) is, it works with nothing, too:
> 
> local foo = nil
> 
> print(foo.bar)
> --> nil
> 
> It kind of breaks my brain. I'm not near a real computer, so I'll have to
> try out what happens when a table with __index assigned to a table returns
> nil... Does the rawget kill the fun? It might not... Probably need more
> sleep to hypothesize. :)

  Okay, try this out (Linux only):

#define _GNU_SOURCE
#include <sys/mman.h>
#include <stdio.h>

int main() {
  int *ptr = NULL;
  if (mmap(0, 4096, PROT_READ|PROT_WRITE,
           MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, -1, 0)
      == MAP_FAILED) {
    perror("Unable to mmap(NULL)");
    fprintf(stderr, "Is /proc/sys/vm/mmap_min_addr non-zero?\n");
    return 1;
  }
  printf("Dereferencing my NULL pointer yields: %d\n", *ptr);
  *ptr = 17;
  printf("Now it's: %d\n", *ptr);
  return 0;
}

  Now, ask yourself---self, is this a Good Thing(TM)?

  -spc (It's too bad you can't mmap() a page read-only, and mmap() a
	different page at the same address write-only [1])

[1]	Or is it a Good Thing(TM) that you can't do that?