Upgrade to Pro — share decks privately, control downloads, hide ads and more …

メタプログラミングとは

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
Avatar for sunnyone sunnyone
April 09, 2016

 メタプログラミングとは

2016.04.09

Avatar for sunnyone

sunnyone

April 09, 2016
Tweet

More Decks by sunnyone

Other Decks in Programming

Transcript

  1. C言語の例(glib) #define G_IMPLEMENT_INTERFACE(TYPE_IFACE, iface_init) { \ const GInterfaceInfo g_implement_interface_info =

    { \ (GInterfaceInitFunc) iface_init, NULL, NULL \ }; \ g_type_add_interface_static (g_define_type_id, TYPE_IFACE, &g_implement_interface_info); \ } G_IMPLEMENT_INTERFACE (GTK_TYPE_EDITABLE, gtk_entry_editable_init) glib の GLib Object SystemはマクロとC言語の仕様を駆使して、 C言語上にクラス/インタフェース構造を表現できるようにしている。 https://developer.gnome.org/gobject/stable/gtype-instantiable-classed.html gtype.h (https://github.com/GNOME/glib/blob/master/gobject/gtype.h)
  2. Rustの例 macro_rules! try { ($expr:expr) => (match $expr { $crate::result::Result::Ok(val)

    => val, $crate::result::Result::Err(err) => { return $crate::result::Result::Err($crate::convert::From::from(err)) } }) } fn write_to_file_using_try() -> Result<(), io::Error> { let mut file = try!(File::create("my_best_friends.txt")); try!(file.write_all(b"This is a list of my best friends.")); println!("I wrote to the file"); Ok(()) } 標準のtry! マクロ (https://github.com/rust-lang/rust/blob/master/src/libcore/macros.rs) このマクロの意味はRust bookのエラーハンドリングを参照 https://rust-lang-ja.github.io/the-rust-programming-language-ja/1.6/book/error-handling.html
  3. Ruby • 普段のメソッドなどの定義そのものがmoduleやclassなどのス コープに入って定義を追加する処理 • コードが動作時に行われることを明示的に実行する – NewClass = Class.new

    do ... end – define_method :new_method do ... end – send によるメソッド呼び出し – method_missing / respond_to – class_eval / instance_eval / module_eval
  4. Rubyの例(ActiveRecord) def method_missing(name, *arguments, &block) match = Method.match(self, name) if

    match && match.valid? match.define send(name, *arguments, &block) else super end end dynamic_matchers.rb (https://github.com/rails/rails/blob/4-2-stable/activerecord/lib/active_record/dynamic_matchers.rb) 定義する def define model.class_eval <<-CODE, __FILE__, __LINE__ + 1 def self.#{name}(#{signature}) #{body} end CODE end 呼び出す Client.find_by_first_name("HogeHoge")
  5. Pythonの例(boto3) def resource(self, service_name, region_name=None, api_version=None, (略) # Create the

    service resource class. cls = self.resource_factory.load_from_definition( resource_name=service_name, single_resource_json_definition=resource_model['service'], service_context=service_context ) return cls(client=client) session.py (https://github.com/boto/boto3/blob/develop/boto3/session.py) def load_from_definition(self, resource_name, single_resource_json_definition, service_context): (略) # Create the name based on the requested service and resource cls_name = resource_name if service_context.service_name == resource_name: cls_name = 'ServiceResource' cls_name = service_context.service_name + '.' + cls_name base_classes = [ServiceResource] (略) return type(str(cls_name), tuple(base_classes), attrs) s3 = boto3.resource('s3')
  6. Javaの例(ModelMapper) static Class<?> proxyClassFor(Class<?> type, Errors errors) throws ErrorsException {

    Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(type); enhancer.setUseFactory(true); enhancer.setUseCache(true); enhancer.setNamingPolicy(NAMING_POLICY); enhancer.setCallbackFilter(METHOD_FILTER); enhancer.setCallbackTypes(new Class[] { MethodInterceptor.class, NoOp.class }); try { return enhancer.createClass(); } catch (Throwable t) { throw errors.errorEnhancingClass(type, t).toException(); } } ProxyFactory.java (https://github.com/jhalterman/modelmapper/blob/master/core/src/main/java/org/modelmapper/internal/ProxyFactory.java) private static void setCallbacks(Object enhanced, MethodInterceptor interceptor) throws Exception { Field callback1 = enhanced.getClass().getDeclaredField("CGLIB$CALLBACK_0"); callback1.setAccessible(true); callback1.set(enhanced, interceptor); 呼び出し毎にinvoke()してくれる interceptするように継承したクラスを生成
  7. C#(Expression Tree)の例(LightNode) // (object[] args) => { new X().M((T1)args[0], (T2)args[1])...

    } var lambda = Expression.Lambda<Action<IDictionary<string, object>, object[]>>( Expression.Call( Expression.MemberInit(Expression.New(classType), envBind), methodInfo, parameters), envArg, args); this.handlerBodyType = HandlerBodyType.Action; this.methodActionBody = lambda.Compile(); OperationHandler.cs (https://github.com/neuecc/LightNode/blob/master/Source/LightNode.Server/OperationHandler.cs) handler.methodActionBody(environment, methodParameters);