ট্রামপোলিন ফাংশন কী?


93

কর্মক্ষেত্রে সাম্প্রতিক আলোচনার সময়, কেউ ট্রামপোলিন ফাংশন উল্লেখ করেছিলেন।

আমি উইকিপিডিয়ায় বর্ণনাটি পড়েছি । কার্যকারিতা সম্পর্কে সাধারণ ধারণা দেওয়া যথেষ্ট, তবে আমি আরও কিছুটা কংক্রিট চাই।

আপনার কাছে কি কোডের একটি সাধারণ স্নিপেট রয়েছে যা ট্রামপোলিন চিত্রিত করবে?


4
মাইক্রোসফ্ট বিশ্বে ট্রাম্পোলাইনগুলি সাধারণত 'থুনস' নামে পরিচিত। [এখানে একটি পৃষ্ঠা]] [1] আন্দ্রে আলেকজান্দ্রেস্কুর "আধুনিক সি ++ ডিজাইন" ---- [1]: Books.google.com/…
মাইকেল


এটি স্ট্যাক ওভারওয়ারফ্লো এড়াতে আপনি সেটজেম্প / লমজিজেএমপি দিয়ে কার্যকর করতে পারেন এমন কিছু কার্যকারিতার সাধারণ আকারটি মূলত।
ইনগো

12
কেন কেউ স্ট্যাকওভারফ্লো এড়াতে চাইবে?
নিকোল

উত্তর:


71

উইকিপিডিয়ায় বর্ণিত 'ট্রাম্পোলিন' এর এলআইএসপি অনুভূতিও রয়েছে:

কিছু এলআইএসপি বাস্তবায়নে ব্যবহৃত হয়, ট্রামপোলিন এমন একটি লুপ যা পুনরাবৃত্তভাবে থাঙ্ক-রিটার্নিং ফাংশনকে অনুরোধ করে। একটি প্রোগ্রামের সমস্ত নিয়ন্ত্রণ স্থানান্তর প্রকাশের জন্য একটি একক ট্রাম্পোলিনই যথেষ্ট; প্রকাশিত একটি প্রোগ্রাম ট্রাম্পোলিন বা "ট্রাম্পোলিনযুক্ত শৈলীতে"; ট্রাম্পোলিন শৈলীতে একটি প্রোগ্রাম রূপান্তর ট্রাম্পোলাইনিং। ট্রাম্পোলিনযুক্ত ফাংশনগুলি স্ট্যাক-ওরিয়েন্টেড ভাষায় লেজ পুনরাবৃত্তির ফাংশন কলগুলি প্রয়োগ করতে ব্যবহার করা যেতে পারে

আসুন আমরা বলি যে আমরা জাভাস্ক্রিপ্টটি ব্যবহার করছি এবং ধারাবাহিকতা-পাসিং-স্টাইলে নির্দোষ ফিবোনাচি ফাংশন লিখতে চাই। যে কারণে আমরা এটি করব তা প্রাসঙ্গিক নয় - উদাহরণস্বরূপ জেএসকে স্কিম বন্দর করা, বা সিপিএসের সাথে খেলতে যা আমাদের যেকোনোভাবে সার্ভার-সাইড ফাংশনগুলি কল করতে ব্যবহার করতে হবে।

সুতরাং, প্রথম প্রচেষ্টা হয়

function fibcps(n, c) {
    if (n <= 1) {
        c(n);
    } else {
        fibcps(n - 1, function (x) {
            fibcps(n - 2, function (y) {
                c(x + y)
            })
        });
    }
}

তবে, n = 25ফায়ারফক্সের সাথে এটি চালানো একটি ত্রুটি দেয় 'অত্যধিক পুনরাবৃত্তি!'! এখন ঠিক এটিই সমস্যা (জাভাস্ক্রিপ্টে টেল-কল অপ্টিমাইজেশন অনুপস্থিত) যা ট্রামপোলিনিংয়ের সমাধান করে। কোনও ফাংশনে একটি (পুনরাবৃত্ত) কল করার পরিবর্তে আসুন আমরা returnসেই ফাংশনটি কল করার জন্য একটি নির্দেশ (থাঙ্ক) আসি, একটি লুপে ব্যাখ্যা করা যায়।

function fibt(n, c) {
    function trampoline(x) {
        while (x && x.func) {
            x = x.func.apply(null, x.args);
        }
    }

    function fibtramp(n, c) {
        if (n <= 1) {
            return {func: c, args: [n]};
        } else {
            return {
                func: fibtramp,
                args: [n - 1,
                    function (x) {
                        return {
                            func: fibtramp,
                            args: [n - 2, function (y) {
                                return {func: c, args: [x + y]}
                            }]
                        }
                    }
                ]
            }
        }
    }

    trampoline({func: fibtramp, args: [n, c]});
}

39

ট্রামপোলিনগুলি প্রয়োগ করে বিভিন্ন ভাষায় বাস্তবিক ফাংশনটির জন্য কয়েকটি উদাহরণ যুক্ত করি:

স্কেল:

sealed trait Bounce[A]
case class Done[A](result: A) extends Bounce[A]
case class Call[A](thunk: () => Bounce[A]) extends Bounce[A]

def trampoline[A](bounce: Bounce[A]): A = bounce match {
  case Call(thunk) => trampoline(thunk())
  case Done(x) => x
}

def factorial(n: Int, product: BigInt): Bounce[BigInt] = {
    if (n <= 2) Done(product)
    else Call(() => factorial(n - 1, n * product))
}

object Factorial extends Application {
    println(trampoline(factorial(100000, 1)))
}

জাভা:

import java.math.BigInteger;

class Trampoline<T> 
{
    public T get() { return null; }
    public Trampoline<T>  run() { return null; }

    T execute() {
        Trampoline<T>  trampoline = this;

        while (trampoline.get() == null) {
            trampoline = trampoline.run();
        }

        return trampoline.get();
    }
}

public class Factorial
{
    public static Trampoline<BigInteger> factorial(final int n, final BigInteger product)
    {
        if(n <= 1) {
            return new Trampoline<BigInteger>() { public BigInteger get() { return product; } };
        }   
        else {
            return new Trampoline<BigInteger>() { 
                public Trampoline<BigInteger> run() { 
                    return factorial(n - 1, product.multiply(BigInteger.valueOf(n)));
                } 
            };
        }
    }

    public static void main( String [ ] args )
    {
        System.out.println(factorial(100000, BigInteger.ONE).execute());
    }
}

সি (বড় সংখ্যক প্রয়োগ ছাড়া দুর্ভাগ্য):

#include <stdio.h>

typedef struct _trampoline_data {
  void(*callback)(struct _trampoline_data*);
  void* parameters;
} trampoline_data;

void trampoline(trampoline_data* data) {
  while(data->callback != NULL)
    data->callback(data);
}

//-----------------------------------------

typedef struct _factorialParameters {
  int n;
  int product;
} factorialParameters;

void factorial(trampoline_data* data) {
  factorialParameters* parameters = (factorialParameters*) data->parameters;

  if (parameters->n <= 1) {
    data->callback = NULL;
  }
  else {
    parameters->product *= parameters->n;
    parameters->n--;
  }
}

int main() {
  factorialParameters params = {5, 1};
  trampoline_data t = {&factorial, &params};

  trampoline(&t);
  printf("\n%d\n", params.product);

  return 0;
}

আপনার ব্যাখ্যা, বিশেষত সি উদাহরণ, সেইসাথে নীচে নেস্টেড ক্রিয়াকলাপ সম্পর্কে নীচের উত্তরের উত্তরটি আমাকে ট্রাম্পলাইনগুলি বুঝতে পেরেছিল। এক ধরণের সাহায্যকারী ফাংশন যা বন্ধ হওয়ার মতো অবস্থা আপডেট করতে ব্যবহার করা যেতে পারে।
বাইট

স্কাল কোডটি সংশোধন করা উচিত if (n < 2) Done(product), এসও আমাকে 1 টি প্রতীক সম্পাদনা করার অনুমতি দেয়নি ...
সর্বোচ্চ

21

আমি আপনাকে একটি উদাহরণ দেব যা আমি একটি অনলাইন গেমের জন্য একটি অ্যান্টি-চিট প্যাচে ব্যবহার করেছি।

গেমটি সংশোধন করার জন্য লোড করা সমস্ত ফাইল আমার স্ক্যান করতে সক্ষম হওয়া প্রয়োজন। সুতরাং এটির সবচেয়ে শক্তিশালী উপায় আমি খুঁজে পেলাম ক্রিয়েটফিলিএর জন্য ট্রাম্পোলিন ব্যবহার করা। সুতরাং যখন গেমটি চালু হয়েছিল তখন আমি getProcAdressress ব্যবহার করে ক্রিয়েটফিলিএর ঠিকানাটি পেয়ে যাব, তারপরে আমি ফাংশনের প্রথম কয়েকটি বাইটগুলি সংশোধন করব এবং সমাবেশ কোডটি সন্নিবেশ করবো যা আমার নিজের "ট্রাম্পলাইন" ফাংশনে চলে যাবে, যেখানে আমি কিছু করব, এবং তারপরে আমি আমার জেএমপি কোডের পরে ক্রিয়েটফিলের পরবর্তী স্থানে ফিরে যাব। এটি নির্ভরযোগ্যভাবে করতে সক্ষম হতে তার চেয়ে কিছুটা জটিল, তবে মূল ধারণাটি কেবল একটি ফাংশনকে হুক করা, এটি অন্য ফাংশনে পুনঃনির্দেশ করতে বাধ্য করা এবং তারপরে মূল ফাংশনে ফিরে যেতে।

সম্পাদনা করুন: মাইক্রোসফ্টের এই ধরণের জিনিসটির জন্য একটি কাঠামো রয়েছে যা আপনি দেখতে পারেন। ডেটোরস বলা হয়


8

আমি বর্তমানে একটি স্কিম দোভাষীর জন্য টেল কল অপ্টিমাইজেশন বাস্তবায়নের উপায়গুলি নিয়ে পরীক্ষা-নিরীক্ষা করছি এবং তাই এই মুহূর্তে ট্রাম্পোলাইনটি আমার পক্ষে সম্ভব হবে কিনা তা জানার চেষ্টা করছি।

আমি এটি বুঝতে পারি, এটি মূলত ট্রামপোলিন ফাংশন দ্বারা সম্পাদিত ফাংশন কলগুলির একটি সিরিজ। প্রতিটি ফাংশনকে থাঙ্ক বলা হয় এবং প্রোগ্রামটি শেষ না হওয়া (খালি ধারাবাহিকতা) হওয়া পর্যন্ত গণনার পরবর্তী ধাপটি প্রদান করে।

ট্রামপোলিন সম্পর্কে আমার বোঝার উন্নতির জন্য আমি এখানে প্রথম কোডের অংশটি লিখেছি:

#include <stdio.h>

typedef void *(*CONTINUATION)(int);

void trampoline(CONTINUATION cont)
{
  int counter = 0;
  CONTINUATION currentCont = cont;
  while (currentCont != NULL) {
    currentCont = (CONTINUATION) currentCont(counter);
    counter++;
  }
  printf("got off the trampoline - happy happy joy joy !\n");
}

void *thunk3(int param)
{
  printf("*boing* last thunk\n");
  return NULL;
}

void *thunk2(int param)
{
  printf("*boing* thunk 2\n");
  return thunk3;
}

void *thunk1(int param)
{
  printf("*boing* thunk 1\n");
  return thunk2;
}

int main(int argc, char **argv)
{
  trampoline(thunk1);
}

ফলাফল স্বরূপ:

meincompi $ ./trampoline 
*boing* thunk 1
*boing* thunk 2
*boing* last thunk
got off the trampoline - happy happy joy joy !

7

নেস্টেড ফাংশনগুলির উদাহরণ এখানে:

#include <stdlib.h>
#include <string.h>
/* sort an array, starting at address `base`,
 * containing `nmemb` members, separated by `size`,
 * comparing on the first `nbytes` only. */
void sort_bytes(void *base,  size_t nmemb, size_t size, size_t nbytes) {
    int compar(const void *a, const void *b) {
        return memcmp(a, b, nbytes);
    }
    qsort(base, nmemb, size, compar);
}

comparবাহ্যিক ফাংশন হতে পারে না, কারণ এটি ব্যবহার করে nbytes, যা কেবলমাত্র sort_bytesকল চলাকালীন বিদ্যমান । কিছু আর্কিটেকচারে, ট্রাম্পোলিন - একটি ছোট স্টাব ফাংশন রানটাইম সময়ে উত্পন্ন হয় এবং এতে বর্তমানের অনুরোধের স্ট্যাক অবস্থান রয়েছে sort_bytes। যখন ফোন করা হয়, তখন comparকোডটি লাফিয়ে সেই ঠিকানাটি পাস করে।

পাওয়ারপিসির মতো আর্কিটেকচারে এই জগাখিরিটির প্রয়োজন হয় না, যেখানে এবিআই নির্দিষ্ট করে যে কোনও ফাংশন পয়েন্টার আসলে "ফ্যাট পয়েন্টার", কাঠামো কার্যকরকারী কোডের পয়েন্টার এবং ডেটাতে অন্য পয়েন্টার উভয় সমন্বিত একটি কাঠামো। যাইহোক, x86-এ, একটি ফাংশন পয়েন্টার কেবল পয়েন্টার।


0

সি এর জন্য, ট্রামপোলিন একটি ফাংশন পয়েন্টার হতে পারে:

size_t (*trampoline_example)(const char *, const char *);
trampoline_example= strcspn;
size_t result_1= trampoline_example("xyzbxz", "abc");

trampoline_example= strspn;
size_t result_2= trampoline_example("xyzbxz", "abc");

সম্পাদনা করুন: আরও মূলত ট্রাম্পোলাইনগুলি সংকলক দ্বারা স্পষ্টভাবে তৈরি করা হবে। এরকম একটি ব্যবহার হ'ল জাম্প টেবিল। (যদিও আরও জটিল আরও স্পষ্টভাবে রয়েছে তবে আপনি জটিল কোড উত্পন্ন করার চেষ্টা শুরু করেছেন))


0

এখন যে সি # এর স্থানীয় ফাংশন রয়েছে , বোলিং গেম কোডিং কাটা ট্রাম্পলিন দিয়ে মার্জিতভাবে সমাধান করা যেতে পারে:

using System.Collections.Generic;
using System.Linq;

class Game
{
    internal static int RollMany(params int[] rs) 
    {
        return Trampoline(1, 0, rs.ToList());

        int Trampoline(int frame, int rsf, IEnumerable<int> rs) =>
              frame == 11             ? rsf
            : rs.Count() == 0         ? rsf
            : rs.First() == 10        ? Trampoline(frame + 1, rsf + rs.Take(3).Sum(), rs.Skip(1))
            : rs.Take(2).Sum() == 10  ? Trampoline(frame + 1, rsf + rs.Take(3).Sum(), rs.Skip(2))
            :                           Trampoline(frame + 1, rsf + rs.Take(2).Sum(), rs.Skip(2));
    }
}

পদ্ধতিটি Game.RollManyবেশ কয়েকটি রোলগুলির সাথে ডাকা হয়: সাধারণত কোনও স্পেস বা স্ট্রাইক না থাকলে 20 রোল।

প্রথম লাইন অবিলম্বে trampoline ফাংশন কল: return Trampoline(1, 0, rs.ToList());। এই স্থানীয় ফাংশনটি রোলস অ্যারেটিকে পুনরাবৃত্তি করে। স্থানীয় ফাংশন (ট্রাম্পোলিন) ট্র্যাভারসালকে দুটি অতিরিক্ত মান দিয়ে শুরু করতে দেয়: frame1 দিয়ে শুরু করুন rsf(এখনও পর্যন্ত ফলাফল) 0।

স্থানীয় ফাংশনের মধ্যে টেরিনারি অপারেটর রয়েছে যা পাঁচটি কেস পরিচালনা করে:

  • খেলা ফ্রেম 11 এ শেষ হয়: এখনও পর্যন্ত ফলাফলটি ফিরিয়ে দিন
  • আর কোনও রোল না থাকলে গেমটি শেষ হয়: এখনও পর্যন্ত ফলাফলটি ফিরিয়ে দিন
  • স্ট্রাইক: ফ্রেম স্কোর গণনা করুন এবং ট্র্যাভারসাল চালিয়ে যান
  • অতিরিক্ত: ফ্রেম স্কোর গণনা করুন এবং ট্র্যাভারসাল চালিয়ে যান
  • সাধারণ স্কোর: ফ্রেম স্কোর গণনা করুন এবং ট্র্যাভারসাল চালিয়ে যান

ট্র্যাভারসাল চালিয়ে যাওয়া আবার ট্রামপোলিন কল করেই করা হয় তবে এখন আপডেট হওয়া মান সহ।

আরও তথ্যের জন্য, অনুসন্ধান করুন: " লেজ পুনরাবৃত্তি সংগ্রহকারী "। মনে রাখবেন যে সংকলক লেজ পুনরাবৃত্তি অপ্টিমাইজ করে না। সুতরাং এই সমাধানটি যতটা মার্জিত হতে পারে, সম্ভবত এটি রোজা রাখা হবে না।


-2
typedef void* (*state_type)(void);
void* state1();
void* state2();
void* state1() {
  return state2;
}
void* state2() {
  return state1;
}
// ...
state_type state = state1;
while (1) {
  state = state();
}
// ...

4
আপনি কেন কোনও মন্তব্য বা ব্যাখ্যা যুক্ত করতে পারেন কেন এটি ট্রামপোলিন?
প্রসুন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.