Home Php C# Sql C C++ Javascript Python Java Go Android Git Linux Asp.net Django .net Node.js Ios Xcode Cocoa Iphone Mysql Tomcat Mongodb Bash Objective-c Scala Visual-studio Apache Elasticsearch Jar Eclipse Jquery Ruby-on-rails Ruby Rubygems Android-studio Spring Lua Sqlite Emacs Ubuntu Perl Docker Swift Amazon-web-services Svn Html Ajax Xml Java-ee Maven Intellij-idea Rvm Macos Unix Css Ipad Postgresql Css3 Json Windows-server Vue.js Typescript Oracle Hibernate Internet-explorer Github Tensorflow Laravel Symfony Redis Html5 Google-app-engine Nginx Firefox Sqlalchemy Lucene Erlang Flask Vim Solr Webview Facebook Zend-framework Virtualenv Nosql Ide Twitter Safari Flutter Bundle Phonegap Centos Sphinx Actionscript Tornado Register | Login | Edit Tags | New Questions | 繁体 | 简体


10 questions online user: 23

0
votes
answers
12 views
+10

Google API python證書OAUTH服務器服務器

0

在我的項目中,我開發了一個python腳本進行檢查並自動在我的Google日曆上創建一個約會。 首先,我從谷歌開發者控制檯OAUTH JSON文件創建,然後驗證和運行我的腳本:Google API python證書OAUTH服務器服務器

SCOPES = 'https://www.googleapis.com/auth/calendar' 
CLIENT_SECRET_FILE = 'client_id.json' 
APPLICATION_NAME = 'Google Calendar API Python Quickstart' 


def get_credentials(): 

home_dir = os.path.expanduser('~') 
credential_dir = os.path.join(home_dir, '.credentials') 
if not os.path.exists(credential_dir): 
    os.makedirs(credential_dir) 
credential_path = os.path.join(credential_dir, 
           'calendar-python-quickstart.json') 

store = Storage(credential_path) 
credentials = store.get() 
if not credentials or credentials.invalid: 
    flow = client.flow_from_clientsecrets(CLIENT_SECRET_FILE, SCOPES) 
    flow.user_agent = APPLICATION_NAME 
    if flags: 
     credentials = tools.run_flow(flow, store, flags) 
    else: # Needed only for compatibility with Python 2.6 
     credentials = tools.run(flow, store) 
    print('Storing credentials to ' + credential_path) 
return credentials 


credentials = get_credentials() 
http = credentials.authorize(httplib2.Http()) 
service = discovery.build('calendar', 'v3', http=http) 

當我從我的本地機器全部完成運行它,但是當我上傳腳本和使用AWS拉姆達所有依賴功能時,我測試了服務器responde:

{ "errorMessage": "module initialization error" }

START RequestId: 2244eefe-e3dd-11e7-a0ce-93ed40a4fa13 Version: $LATEST module initialization error: [Errno 30] Read-only file system: '/home/sbx_user1060'

我想這是因爲身份驗證方法存儲和retrive本地計算機上的JSON證書文件,但我怎麼能驗證和從服務器到服務器運行代碼,而不是客戶端 - 服務器?

在此先感謝

沙发
0
1

在你的代碼的憑證部分,將其更改爲得到機器的默認憑據,是這樣的:

#import GoogleCredentials 
from oauth2client.client import GoogleCredentials 

credentials = GoogleCredentials.get_application_default() 
service = discovery.build('calendar', 'v3', credentials=credentials) 

在您的拉姆達配置集GOOGLE_APPLICATION_CREDENTIALS作爲環境變量的關鍵和你的證書json文件名作爲值。

它適用於我所有使用google api的lambda表達式。

0
votes
answers
10 views
+10

AWS Lambda。錯誤= 20(不是目錄)當FFmpeg移動到/ tmp

0

我正在使用ffmpeg-cli-wrapper從我上傳到AWS lambda的應用程序運行FFmpeg。我最初得到AWS Lambda。錯誤= 20(不是目錄)當FFmpeg移動到/ tmp

錯誤= 13權限試圖通過包裝ProcessBuilder調用它的時候被拒絕

。我的初始解決方案是在上傳之前對chmod 755 ffmpeg,但它沒有幫助。

有關信息,我的FFmpeg和ffprobe文件位於以下類路徑中:static/ffmpeg/ffmpegstatic/ffmpeg/ffprobe。它們也是靜態鏈接的。

AWS Lambda permission denied when trying to use ffmpeg

我試着按照上面的例子中給出的說明,但是當我嘗試執行或者MV或cp命令:Runtime.exec("mv " + pathToFFmpeg + " /tmp"),我得到的

錯誤= 20,沒有目錄

錯誤。

我知道我有FFmpeg的正確路徑,因爲以下命令mv *pathToFFmpeg* *an arbitrary name*運行時沒有錯誤,這意味着該文件在那裏,因此mv命令只是將它重命名爲它應該執行的操作。

+0

該錯誤似乎沒有道理,但您的主目錄不可寫,所以移動不應該工作。嘗試'cp'。 –

+0

嗯,我通過切換到'ProcessBuilder'(之前使用'Runtime.exec()')來解決這個問題。現在,當訪問/ tmp中的ffmpeg(即使在'chmod 755''/ tmp中的文件之後),我又得到了'error = 13,Permission denied',我應該問一個新的問題嗎? –

+0

我現在修復了這個問題!我最初是從Windows 10 bash中獲得文件的,但是我發現它一直沒有任何影響。我發現了一種在Windows中做同樣事情的方法,現在我可以使用FFmpeg。謝謝你的幫助! –

沙发
0
0

我是從Windows環境創建JAR的,我的理解是,在lambda環境中的chmod 755'ing沒有效果因此。

解決方案:在Windows中JARing之前,將'Everyone'組權限授予文件或任何可能包含的目錄。它沒有顯示給我,所以我不得不添加權限組。這似乎解決了我得到的錯誤= 20和錯誤= 13錯誤。 Screenshot of menu。請注意,我仍然必須在lambda函數中包含chmod 755,否則我會再次得到錯誤= 13。

我也遇到了一個錯誤= 2(無此文件或目錄),這是我到目前爲止已經能夠通過解析:
一)開關從Runtime.exec()ProcessBuilder
                         (我猜的Runtime.exec()小 '精',需要額外的配置)
b)使用cp,而不是mv
c)從相同的方法運行ProcessBuilder我調用FFmpeg,而不是調用同一類的不同方法來完成此操作。不知道爲什麼這是...

0
votes
answers
8 views
+10

C#Lambda表達式到VB.Net

0

我想轉換C#Lambda表達式到VB.Net

cfind.OnResponseReceived = (DicomCFindRequest rq, DicomCFindResponse rp) => { 
    Console.WriteLine("Study UID: {0}", rp.Dataset.Get<string>(DicomTag.StudyInstanceUID)); 
}; 

到VB.Net

但是, 既不

AddHandler cfind.OnResponseReceived, AddressOf onResponse 

也不

AddHandler cfind.OnResponseReceived, Sub(rq, rp) 
     onCFindResponse(rq, rp) 
End Sub 

事作品.. 我該如何轉換它?

+0

的作用,並不等同 - 你重構原始的C#Console.WriteLine行動統一到一個單獨的'Sub'? – StuartLC

+0

這是一項任務,而不是事件訂閱。注意=,沒有+ =。因此使用AddHander是不正確的。賦值在VB.NET中的作用相同,您可以使用=。使用Sub,而不是Function。 –

沙发
0
2

這應該是對應的VB.NET:要執行

cfind.OnResponseReceived = Sub(rq As DicomCFindRequest, rp As DicomCFindResponse) 
    Console.WriteLine("Study UID: {0}", rp.Dataset.[Get](Of String)(DicomTag.StudyInstanceUID)) 

End Sub 
+0

由於該方法不返回任何東西,它應該是一個'Sub',而不是'Function'。 –

+0

@visualvincent你是對的,謝謝。更新了答案。 – CodingYoshi

0
votes
answers
17 views
+10

啓用X射線對lambda函數進行主動跟蹤

2

我正在嘗試將活動跟蹤添加到2個lambda函數中,一個在Node中,另一個在Python中。 我的服務角色擁有的所有XRayWriteAccess權限,我點擊高級>啓用活動追蹤,請參閱權限信息,點擊保存,並看到:啓用X射線對lambda函數進行主動跟蹤

enter image description here

網絡搜索沒有返回任何結論,任何想法?

+0

嘗試使用AWS CLI啓用跟蹤,看看會產生什麼樣的輸出:'AWS拉姆達最新情況:功能配置 - 功能名稱 --tracing-config Mode = Active' – hjpotter92

+0

令人驚訝的是,此命令的唯一作用是啓用沒有打嗝的跟蹤。如果你想要點,讓它成爲答案?以下是輸出,已清理:https://gist.github.com/xShirase/8c1a421b056272520388e3039cc27c21 – xShirase

沙发
0
3

您的Web控制檯可能是預填一些表單域(我責怪它的瀏覽器)。如果你只是想使X射線主動跟蹤的功能,撥打電話到update-function-configuration與AWS CLI:

aws lambda update-function-configuration  
    --function-name <name>  
    --tracing-config Mode=Active 
0
votes
answers
8 views
+10

使用.NET核心在aws lambda中讀取excel文件

2

我有一個在AWS Lambda中運行的.NET Core應用程序。我現在有一個需求來閱讀並對Excel文件進??行一些計算。我發現對於Excel在.NET的核心解析兩個庫,但每次似乎並不能夠在lambda運行不同的原因:使用.NET核心在aws lambda中讀取excel文件

我有任何除了選擇:

  1. 等待拉姆達支持.NET核2.0
  2. 不使用lambda

謝謝。

+2

此鏈接可能有所幫助:https://stackoverflow.com/questions/33436525/how-to-parse-excel-rows-back-to-types-using-epplus/37746915#37746915 –

沙发
0
2

如果您正在尋找替代選項,則可以使用Google表格和API代替使用Excel。

可以從Lamda調用Google Sheets API,如果存在複雜的讀寫操作,還可以在Google Sheet中編寫應用程序腳本,並從Lambda調用它。

我們處於類似的情況,並將Excel導入到Google表格,並能夠進行計算工作。

0
votes
answers
10 views
+10

無法在命令行上啓動Amazon Lambda(HelloWorld示例)

1

我遵循Amazon的教程,在悉尼地區創建HelloWorld lambda函數。它在AWS控制檯上工作。無法在命令行上啓動Amazon Lambda(HelloWorld示例)

enter image description here

然後我試圖做到這一點的命令行:

aws lambda invoke --invocation-type RequestResponse --function-name HelloWorld --region Sydney --payload '{"key1":"value1", "key2":"value2", "key3":"value3"}' outputfile.txt

錯誤:

Could not connect to the endpoint URL: " https://lambda.Sydney.amazonaws.com/2015-03-31/functions/HelloWorld/invocations "

我覺得我的安全密鑰是工作,因爲上市的以下命令我的S3桶工作:

aws s3api list-buckets # Worked, so the security keys should work

沙发
0
2

根據您發出的用於調用Lambda函數的CLI命令,似乎問題在於region參數。

取而代之的是區域參數值「悉尼」,以「AP-東南-2」,這是亞太(悉尼)地區代碼替換它。

0
votes
answers
4 views
+10

How is “int main(){(([](){})());}” valid C++?

I recently came across the following esoteric piece of code.

int main(){(([](){})());}

Reformat it as follows to make it more readable:

int main(){
    (([](){})());   //  Um... what?!?!
}

But I can't get my head around how (([](){})()) is valid code.

  • It doesn't look like function pointer syntax.
  • It can't be some operator overloading trick. The code compiles as is.

Google didn't help much with this all-symbol search. But it compiles in Visual Studio 2010 and outputs nothing. There were no errors, and no warnings. So it looks like valid code.

I've never seen any valid code that is so bizarre outside of Javascript and C function pointers.

Can someone explain how this is valid C++?

0
votes
answers
11 views
+10

如何在JavaScript中實現lambda/anonymous函數

1

所以我想用JavaScript實現LISP的一個子集。我被困在與lambda相關的兩件事上。如何在JavaScript中實現lambda/anonymous函數

如何實現創建lambda的能力,並同時給它的參數,並立即評估?例如:

((lambda(x)(* x 2)) 3) 

現在我硬編碼這個功能在我的eval環這樣的:

else if (isArray(expr)){ 
     if (expr[0][0] === 'lambda' || expr[0][0] === 'string') { 
     console.log("This is a special lambda"); 
     var lambdaFunc = evaluate(expr[0], env) 
     var lambdaArgs = []; 
     for(var i = 1; i < expr.length; i++){ 
      lambdaArgs.push(expr[i]); 
     }   
     return lambdaFunc.apply(this, lambdaArgs); 
     } 

現在這個工作,如果我寫在參數上面拉姆達它會評估到6,但是,我想知道是否有更聰明的方式來實現這一點?

如果一個lambda改爲綁定到一個符號,例如:

(define fib (lambda(n) 
    (if (< n 2) 1 
    (+ (fib (- n 1))(fib (- n 2))) 
    ))) 

在這種情況下,(定義FIB)部分將由EVAL-環路第一被評??估,正如如果FIB只是被分配一個號碼:

else if (expr[0] === 'define') { // (define var value) 
     console.log(expr + " is a define statement"); 
     var newVar = expr[1]; 
     var newVal = evaluate(expr[2], env); 
     env.add(newVar, newVal); 
     return env; 
    } 

而λ-功能正在創建這樣的:

else if (expr[0] === 'lambda') { // (lambda args body) 
     console.log(expr + " is a lambda statement"); 
     var args = expr[1]; 
     var body = expr[2]; 
     return createLambda(args, body, env); 
    } 

獨立的函數來創建拉姆達:

function createLambda(args, body, env){ // lambda args body 
    function runLambda(){ 
     var lambdaEnvironment = new environment(env, "lambda environment"); 
     for (var i = 0; i < arguments.length; i++){ 
      lambdaEnvironment.add(args[i], evaluate(arguments[i], env)); 
     } 
     return evaluate(body, lambdaEnvironment); 
    } 
    return runLambda; 
} 

此工作正常的lambda如:

(define range (lambda (a b) 
    (if (= a b) (quote()) 
    (cons a (range (+ a 1) b))))) 

(define fact (lambda (n) 
    (if (<= n 1) 1 
    (* n (fact (- n 1)))))) 

例如,(範圍0 10)返回從0到10

列表但是,如果我在lambda內嘗試lambda,它不起作用。例如:

(define twice (lambda (x) (* 2 x))) 
(define repeat (lambda (f) (lambda (x) (f (f x))))) 

我希望下面的返回40:

((repeat twice) 10) 

但是,相反,它返回一個列表看起來像這樣:

function runLambda(){ var lambdaEnvironment = new environment(env, "lambda 
environment"); for (var i = 0; i < arguments.length; i++){ 
lambdaEnvironment.add(args[i], evaluate(arguments[i], env)); } return 
evaluate(body, lambdaEnvironment); },10 

任何想法可能會丟失這裏?

完整的JavaScript;

//functions for parsing invoice String 

function parse(exp) { 
    return readFromTokes(tokenize(exp));//code 
} 


function isNumeric(arg){ 
    return !isNaN(arg); 
} 

function isArray(obj){ 
    return !!obj && obj.constructor === Array; 
} 

function readFromTokes(exp){ 
    //Create abstract syntax tree 
    if (exp.length == 0) { 
    } 
    var token = exp.shift(); 
    if (token == '('){ 
     var L = []; 
     while (exp[0] != ')') { 
     L.push(readFromTokes(exp)); 
     }   
     exp.shift(); //remove end paranthesis 
     return L; 
    } else { 
     if (token == ')') { 
      console.log("Unexpected)"); 
     } else { 
      return atom(token); 
     } 
    } 
} 

function tokenize(exp){ 
    //Convert a program in form of a string into an array (list) 
    var re = /(/g; 
    var re2 = /)/g; 
    exp = exp.replace(re, " ("); 
    exp = exp.replace(re2, ") "); 
    exp = exp.replace(/s+/g, ' '); 
    exp = exp.trim().split(" "); 
    return exp; 
} 

function atom(exp){ 
    if (isNumeric(exp)) { 
    return parseInt(exp); //A number is a number 
    } else { 
     return exp; //Everything else is a symbol 
    } 
} 

function environment(parentEnvironment, name){ 
    var bindings = []; 
    var parent = parentEnvironment; 
    var name = name; 

    function add(variable, value){ 
     console.log("variable: " + variable + " value: " + value); 
     bindings.push([variable, value]); 
    } 

    function printName(){ 
     console.log(name); 
    } 

    function print() { 
     console.log("printing environment: ") 
     for (var i = 0; i < bindings.length; i++){ 
      console.log(bindings[i][0] + " " + bindings[i][1]); 
     } 
    } 

    function get(variable){ 
     for (var i = 0; i < bindings.length; i++){ 
      if (variable == bindings[i][0]){ 
       return bindings[i][1]; 
      } 
     } 
     if (parent != null){ 
      return parent.get(variable); 
     } else { 
     console.log("No such variable"); 
      return false; 
     } 
    } 

    function getParent(){ 
     return parent; 
    } 

    this.add = add; 
    this.get = get; 
    this.getParent = getParent; 
    this.print = print; 
    this.printName = printName; 
    return this; 
} 

function addPrimitives(env){ 
    env.add("+", function() {var s = 0; for (var i = 0; i<arguments.length;i++){ s += arguments[i];} return s}); 
    env.add("-", function() {var s = arguments[0]; for (var i = 1; i<arguments.length;i++){ s -= arguments[i];} return s}); 
    env.add("*", function() {var s = 1; for (var i = 0; i<arguments.length;i++){ s *= arguments[i];} return s}); 
    env.add("/", function(x, y) { return x/y }); 
    env.add("false", false); 
    env.add("true", true); 
    env.add(">", function(x, y){ return (x > y) }); 
    env.add("<", function(x, y){ return (x < y) }); 
    env.add("=", function(x, y){ return (x === y)}); 
    env.add(">=", function(x, y){ if (x >= y){return true;} else {return false;}}); 
    env.add("<=", function(x, y){ if (x <= y){return true;} else {return false;}}); 
    env.add("eq?", function() {var s = arguments[0]; var t = true; for(var i = 1; i<arguments.length; i++){ if (arguments[i] != s) {t = false }} return t;}); 
    env.add("cons", function(x, y) { var temp = [x]; return temp.concat(y); }); 
    env.add("car", function(x) { return x[0]; }); 
    env.add("cdr", function(x) { return x.slice(1); }); 
    env.add("list", function() { return Array.prototype.slice.call(arguments); }); 
    env.add("list?", function(x) {return isArray(x); }); 
    env.add("null", null); 
    env.add("null?", function (x) { return (!x || x.length === 0); }); 
} 


function createLambda(args, body, env){ // lambda args body 
    function runLambda(){ 
    var lambdaEnvironment = new environment(env, "lambda environment"); 
     for (var i = 0; i < arguments.length; i++){ 
      lambdaEnvironment.add(args[i], evaluate(arguments[i], env)); 
     } 
     return evaluate(body, lambdaEnvironment); 
    } 
    return runLambda; 
} 

function evaluate(expr, env) { 
    console.log(expr + " has entered evaluate loop"); 
    if (typeof expr === 'string') { 
     console.log(expr + " is a symbol"); 
     return env.get(expr); 
    } else if (typeof expr === 'number') { 
     console.log(expr + " is a number"); 
     return expr; 
    } else if (expr[0] === 'define') { // (define var value) 
     console.log(expr + " is a define statement"); 
     var newVar = expr[1]; 
     var newVal = evaluate(expr[2], env); 
     env.add(newVar, newVal); 
     return env; 
    } else if (expr[0] === 'lambda') { // (lambda args body) 
     console.log(expr + " is a lambda statement"); 
     var args = expr[1]; 
     var body = expr[2]; 
     return createLambda(args, body, env); 
    } else if (expr[0] === 'quote') { 
     return expr[1]; 
    } else if (expr[0] === 'cond'){ 
     console.log(expr + " is a conditional"); 
     for (var i = 1; i < expr.length; i++){ 
      var temp = expr[i]; 
      if (evaluate(temp[0], env)) { 
       console.log(temp[0] + " is evaluated as true"); 
       return evaluate(temp[1], env); 
      } 
     } 
     console.log("no case was evaluated as true"); 
     return; 
    } else if (expr[0] === 'if') { 
     console.log(expr + "is an if case"); 
     return function(test, caseyes, caseno, env){ 
      if (test) { 
       return evaluate(caseyes, env); 
      } else { 
       return evaluate(caseno, env); 
      } 
     }(evaluate(expr[1], env), expr[2], expr[3], env); 
    } else if (typeof expr[0] === 'string'){ 
     console.log(expr + " is a function call"); 
     var lispFunc = env.get(expr[0]); 
     var lispFuncArgs = [];   
     for(var i = 1; i < expr.length; i++){ 
     lispFuncArgs.push(evaluate(expr[i], env)); 
     } 
     return lispFunc.apply(this, lispFuncArgs); 
    } else if (isArray(expr)){ 
     if (expr[0][0] === 'lambda' || expr[0][0] === 'string') { 
      console.log("This is a special lambda"); 
      var lambdaFunc = evaluate(expr[0], env) 
      var lambdaArgs= []; 
      for(var i = 1; i < expr.length; i++){ 
       lambdaArgs.push(expr[i]); 
      }   
      return lambdaFunc.apply(this, lambdaArgs); 
     } else { 
      console.log(expr + " is a list"); 
      var evaluatedList = []; 
      for(var i = 0; i < expr.length; i++){ 
       evaluatedList.push(evaluate(expr[i], env)); 
      } 
      return evaluatedList; 
     } 
    } else { 
     console.log(expr + " cannot be interpreted"); 
    } 
} 


var globalEnvironment = new environment(null, "Global"); 

addPrimitives(globalEnvironment); 

function start(string) { 
    return evaluate(parse(string), globalEnvironment); 
} 

var output = function (string) { 
    try { 
     document.getElementById('debugdiv').innerHTML = start(string); 
    } catch (e) { 
     document.getElementById('debugdiv').innerHTML = e.name + ': ' + e.message; 
    } 
}; 

Full HTML;

<html> 
    <head> 
     <meta content="text/html; charset=UTF-8" http-equiv="Content-Script-Type" content="text/javascript"> 
     <title>LISP in JavaScript</title> 
     <script type="text/javascript" src="lisp.js"></script> 
    </head> 
    <body> 
     <form id="repl" name="repl" action="parse(prompt.value)"> 
     lisp==&gt; 
      <input id="prompt" size="200" value="" name="prompt" maxlength="512"> 
      <br> 
      <input type=button style="width:60px;height:30px" name="btnEval" value="eval" onclick="output(prompt.value)"> 
      <br> 
      </form> 
     <div id="debugdiv" style="background-color:orange;width=100px;height=20px"> 
     </div>   
    </body> 
</html> 

進一步的想法,建議和意見當然也是受歡迎的。 謝謝!

+3

'(X => X * 2)(3)'我敢打賭,它更容易transpile&'eval'它... –

+1

這個問題是非常接近到「太寬泛」,有點接近「幫助我的代碼不工作」。請考慮將其調整到提出問題所需的最低限度。 – bhspencer

沙发
0
2

您不檢查操作數的結構以查看它是否爲lambda您操作數evaleval的標準方法是檢查它是否爲原始類型,然後檢查特殊形式和宏,然後在應用之前評估運算符和操作數。

只需刪除其中expr[0][0] === 'lambda' || expr[0][0] === 'string'是真實的一部分,而不是隻返回形式的評估需要apply操作數:

else if (isArray(expr)){ 
    const fn = evaluate(expr[0], env); 
    const evaluatedList = []; 
    for(var i = 1; i < expr.length; i++){ 
    evaluatedList.push(evaluate(expr[i], env)); 
    } 
    return fn(...evaluatedList); 
} 

createLambda是錯誤的,因爲你正在評估中的參數錯誤的環境。因爲參數已經評價這將是正確的:

function createLambda(args, body, env){ // lambda args body 
    function runLambda(){ 
    const lambdaEnvironment = new environment(env, "lambda environment"); 
    for (let i = 0; i < arguments.length; i++){ 
     lambdaEnvironment.add(args[i], arguments[i]); 
    } 
    return evaluate(body, lambdaEnvironment); 
    } 
    return runLambda; 
} 
0
votes
answers
6 views
+10

Java中的Lambda表達式機制

0

我剛剛在一本書中讀到,當一個lambda表達式被分配給一個函數接口時,那麼它會爲lambda表達式和該類型的一個實例設置「target type」(即,功能接口的類型)是使用作爲功能接口中抽象方法實現的lambda表達式創建的。Java中的Lambda表達式機制

我的問題:如果是這樣,那麼是否意味着lambda表達式是不是真的獨立的方法。作爲這樣的新類型的元素帶入語言,而只是簡單地表達一個匿名類更緊湊的方式因此僅僅在編譯器方面增加了一些功能(就像泛型一樣)?

此外,方法引用如何符合那個,特別是與任何對象沒有關聯的靜態方法?例如,當一個方法對一個實例方法的引用被分配給一個功能接口時,那麼將使用該方法的封裝對象,但是在靜態方法的情況下會發生什麼 - 它們不與任何對象相關聯。

+0

的JLS上lambda表達式[第15.27](https://docs.oracle.com/javase/specs/jls/se9/html/jls-15.html#jls-15.27)和[段15.13(HTTPS ://docs.oracle.com/javase/specs/jls/se9/html/jls-15.html#jls-15.13)方法引用爲您提供了答案。 –

沙发
0
1

如果是這樣,那麼是否意味着lambda表達式是不是真的獨立的方法。作爲這樣的新類型的元素帶入語言,

正確,lambda表達式被編譯成一個合成常規方法名稱

但是隻是表達一個匿名類的更簡潔的方式,因此僅僅是在編譯器端添加設施(就像泛型一樣)?

不,它不僅在編譯器方面。在涉及的JVM中也有代碼,因此編譯器不必爲lambda表編寫類文件。

此外,方法引用如何符合那個,特別是與任何對象沒有關聯的靜態方法?

方法引用與lambda表達式沒有什麼不同:在運行時,必須有一個實現函數接口的對象。在調用對象的「SAM」時,此方法將調用引用的方法。

例如,當一個方法參考實例方法被分配給一個功能接口然後被用於該方法中的對象封裝,

不,它不能被使用。讓我們用System.out::println方法參考採取下面的例子:

Arrays.asList("A", "B").forEach(System.out::println); 

List<E>.forEach()期望一個Consumer<? super E>限定方法void accept(E e)。編譯器需要在類文件中生成字節代碼和其他信息,以便在運行時JVM可以使用方法void accept(E e)生成一個實現Consumer<E>的類。這個生成的方法然後調用System.out.println(Object o)

運行時生成的類會看起來像

class $$lambda$xy implements Consumer<Object> { 
    private PrintStream out; 

    $$lambda$xy(PrintStream out) { 
     this.out = out; 
    } 

    void accept(Object o) { 
     out.println(o); 
    } 
} 

你在徵求意見的問題:「爲什麼不直接分配到實例及其方法?」

讓我們擴展的例子一點點:

static void helloWorld(Consumer<String> consumer) { 
    consumer.apply("Hello World!"); 
} 

public static void main(String[] args) { 
    helloWorld(System.out::println); 
} 

要編譯,編譯器已經生成的字節碼,創建實施Consumer<String>對象(因此它可以傳遞對象爲helloWorld())。這個對象某種程度上具有存儲在調用它的accept(x)方法有調用println(x)System.out PrintStream的信息。

其他語言可能有其他名稱或概念的這種對象 - 在Java中建立的概念是「匿名類實現接口和匿名類的對象」。

如何對象存儲這些信息?那麼,你可以發明一些超酷的新方式來存儲這些信息。 Java語言設計師決定,一個匿名類將會足夠好 - 暫時。但他們有先見之明,如果有人提出一個更有效的新思路來實現它,這應該很容易集成到Java生態系統(Java編譯器和JVM)中。

所以,他們也決定創建匿名類在編譯時間,但讓編譯器只寫了必要的信息在類文件。現在JVM可以在運行時確定存儲信息的最佳方式(在正確的對象上調用正確的方法)是什麼。

+0

感謝您的詳細回覆。但我仍然有一個很難理解的是:爲什麼會「的JVM生成一個類實現消費者與的方法無效接受(E E)」時,其實施方法是類要調用實例(通過它的實際對象)來執行功能界面的合同嗎?爲什麼不直接分配給實例及其方法?你相信這是因爲實例沒有裝飾性地實現接口? – Learnerer

+0

@Learnerer我已經更新了我的答案,希望這可以幫助 –

+0

也許混淆是由於編程模型和實現機制之間的干擾。我很感謝你的回答。 – Learnerer

板凳
0
0

例如,當一個方法參考實例方法被分配 到功能接口,則使用該 方法封裝的對象,但在靜態方法中的情況下,會發生什麼 - 那些不與任何物體相關聯。

這取決於上下文。假設我們有一個靜態的Utils#trim(String)方法,它明顯會修剪給定的字符串。

現在,最好有一個List<String> list並讓它有一些字符串。我們可以這樣做:

list.stream().map(Utils::trim).collect(Collectors.toList());

正如您所看到的,在給定的上下文中,我們使用lambda靜態方法參考,以便使用列表中的每個字符串作爲Utils::trim方法的輸入參數。

+0

謝謝。但我真的不問如何使用lambdas或方法引用,我只是想弄清楚幕後的工作 - 它們是如何實現的 – Learnerer

0
votes
answers
11 views
+10

Javac不能推斷類型,除非lambda表達式被內聯

0

我有以下的使用Vavr的Java代碼片段。類型檢查失敗,除非我內聯一個參數。Javac不能推斷類型,除非lambda表達式被內聯

爲什麼下面的代碼不能被編譯器接受?

import io.vavr.Function1; 
import io.vavr.Tuple; 
import io.vavr.Tuple2; 
import io.vavr.collection.List; 
import io.vavr.Option; 

import static io.vavr.collection.List.unfoldRight; 

class A {} 
class B {} 
class Main { 
    Function1<A, Option<Tuple2<B, A>>> f = (a) -> Option.of(Tuple.of(new B(), new A())); 
    List<B> L0 = unfoldRight(new A(), f); // * 
    List<B> L1 = unfoldRight(new A(), (a) -> Option.of(Tuple.of(new B(), new A())); 

    Option<Tuple2<B, A>> g(A a) { return Option.of(Tuple.of(new B(), new A())); } 
    List<B> L2 = unfoldRight(new A(), (a) -> g(a)); // ** 
} 


// * Compilation fails with: "Incompatible equality constraint: ? extends T and A" 

// ** Compilation fails with: "Incompatible equality constraint: ? extends A and A" 

下面是來自Vavr庫unfoldRight方法簽名:

static <T, U> List<U> unfoldRight(T seed, Function<? super T, Option<Tuple2<? extends U, ? extends T>>> f) 

,這裏是在Github上的文檔的鏈接相同:

https://github.com/vavr-io/vavr/blob/master/vavr/src/main/java/io/vavr/collection/List.java#L644-L671

沙发
0
1

的關鍵是, Option<Tuple<A, B>>不是Option<Tuple<? extends A, ? extends B>>的一個實例(雖然它是Option<? extends Tuple<? extends A, ? extends B>>)。

考慮一個List<Map<A, B>>List<Map<? extends A, ? extends B>>(從類型安全角度與您的代碼相同)的情況。如果你可以寫:

List<Map<A, B>> list = new ArrayList<>(); 

// Compiler error! Pretend it's OK, though. 
List<Map<? extends A, ? extends B>> list2 = list; 

Map<SubclassOfA, SubclassOfB> map = new HashMap<>(); 
list2.add(map); 

list.get(0).put(new A(), new B()); 

現在這是一個問題,因爲map包含一個鍵/值對類型A,B,不SubclassOfA,SubclassOfB的。因此,如果您試圖從map獲取東西,則會得到ClassCastException

// ClassCastException! 
SubclassOfA soa = map.keySet().iterator().next(); 

Ideone demo

因此,它是由編譯器不允許的。

如果list2被宣佈爲List<? extends Map<? extends A, ? extends B>>,則不能撥打list2.add(map),因此您無法獲得相同的問題。因此,該分配將被允許。

添加通配符上界到你的類型:

Function1<A, Option<Tuple2<? extends B, ? extends A>>> f = ... 
Option<Tuple2<? extends B, ? extends A>> g(A a) { ... } 
+0

哦,對了,這是'''不兼容的不等式約束:(?延伸A,A)'''不'''不兼容的不等式約束:( ?擴展A,?擴展A)'''。非常感謝! – Zaaier