Is there any way to make an Apex method parameter lazy?Get Total Permutations of child objects in a list of...
Why did Mr. Elliot have to decide whose boots were thickest in "Persuasion"?
Why didn't Tom Riddle take the presence of Fawkes and the Sorting Hat as more of a threat?
How to write cases in LaTeX?
Crack the bank account's password!
Is there a file that always exists and a 'normal' user can't lstat it?
Am I correct in stating that the study of topology is purely theoretical?
Why did Ylvis use "go" instead of "say" in phrases like "Dog goes 'woof'"?
How do you funnel food off a cutting board?
Use Collectors.groupingby to create a map to a set
A question about partitioning positivie integers into finitely many arithmetic progresions
Concatenating two int[]
Writing dialogues for characters whose first language is not English
Sharepoint metadata URL
Is `Object` a function in javascript?
The No-Straight Maze
Single-row INSERT...SELECT much slower than separate SELECT
Taking headphones when quitting job
A starship is travelling at 0.9c and collides with a small rock. Will it leave a clean hole through, or will more happen?
What makes papers publishable in top-tier journals?
I have trouble understanding this fallacy: "If A, then B. Therefore if not-B, then not-A."
Buying a "Used" Router
Non-Cancer terminal illness that can affect young (age 10-13) girls?
Website seeing my Facebook data?
Does it take energy to move something in a circle?
Is there any way to make an Apex method parameter lazy?
Get Total Permutations of child objects in a list of listsProcessInstanceWorkitems not created when running an Approval Process unit testWill SFDC manufacture batches from concurrent operations?Order of execution of controller method calls during rerenderCalling a method with List<string> Ids parameterIs there an easy way to sync the Default Account Team of an User to all accounts he owns by APEX?Is there any way to LIKE a chatter post in the context of another user?Need a Help to Convert Workflow Formula field into ApexIs there a Salesforce method to validate Remote Objects Query Criteria and turn it into dynamic SOQL?Is applying a LIMIT to a Count() query an optimization?
Let's say I want to call a method like:
doSomething(a.b.c.d.e.f());
I know that this might be an expensive operation and a, a.b, a.b.c, a.b.c.d, and a.b.c.d.e might all be null, however I would rather deal with all these possibilities within doSomething()
is there any way I can defer that operation until I want/need it?
(I'm 99% certain the answer is 'no', but I hope to learn that I'm wrong.)
apex null-pointer method lazy-loading
add a comment |
Let's say I want to call a method like:
doSomething(a.b.c.d.e.f());
I know that this might be an expensive operation and a, a.b, a.b.c, a.b.c.d, and a.b.c.d.e might all be null, however I would rather deal with all these possibilities within doSomething()
is there any way I can defer that operation until I want/need it?
(I'm 99% certain the answer is 'no', but I hope to learn that I'm wrong.)
apex null-pointer method lazy-loading
1
This Idea would help, though not as nice as having a shortcut like?
null checks available in .Net.
– sfdcfox
5 hours ago
add a comment |
Let's say I want to call a method like:
doSomething(a.b.c.d.e.f());
I know that this might be an expensive operation and a, a.b, a.b.c, a.b.c.d, and a.b.c.d.e might all be null, however I would rather deal with all these possibilities within doSomething()
is there any way I can defer that operation until I want/need it?
(I'm 99% certain the answer is 'no', but I hope to learn that I'm wrong.)
apex null-pointer method lazy-loading
Let's say I want to call a method like:
doSomething(a.b.c.d.e.f());
I know that this might be an expensive operation and a, a.b, a.b.c, a.b.c.d, and a.b.c.d.e might all be null, however I would rather deal with all these possibilities within doSomething()
is there any way I can defer that operation until I want/need it?
(I'm 99% certain the answer is 'no', but I hope to learn that I'm wrong.)
apex null-pointer method lazy-loading
apex null-pointer method lazy-loading
asked 8 hours ago
Brian KesslerBrian Kessler
1,6411131
1,6411131
1
This Idea would help, though not as nice as having a shortcut like?
null checks available in .Net.
– sfdcfox
5 hours ago
add a comment |
1
This Idea would help, though not as nice as having a shortcut like?
null checks available in .Net.
– sfdcfox
5 hours ago
1
1
This Idea would help, though not as nice as having a shortcut like
?
null checks available in .Net.– sfdcfox
5 hours ago
This Idea would help, though not as nice as having a shortcut like
?
null checks available in .Net.– sfdcfox
5 hours ago
add a comment |
1 Answer
1
active
oldest
votes
Not exactly, but you can do something like lazy evaluation by making use of the Callable
interface (or rolling your own). Here's an example using Callable
...
To start with, a test:
@IsTest private class LazyTest {
@TestSetup static void setup() {
List<Account> accounts = new List<Account> {
new Account(Name = 'A'),
new Account(Name = 'B')};
insert accounts;
List<Contact> contacts = new List<Contact> {
new Contact(LastName = '1', AccountId = accounts[0].Id),
new Contact(LastName = '2', AccountId = accounts[1].Id)};
insert contacts;
}
@IsTest static void testBehavior() {
Callable lazyContacts = new LazyContacts(new LazyAccounts('A'));
// No calls made yet, so I can pass this around at no great cost
System.assertEquals(0, Limits.getQueries());
// OK, I've decided I need those contacts now...
List<Contact> results = (List<Contact>)lazyContacts.call(null, null);
System.assertEquals(2, Limits.getQueries());
System.assertEquals(1, results.size());
System.assertEquals('1', results[0].LastName);
}
}
In the test, lazyContacts
is not yet the Contacts I'm looking for. It's like a Callable
that will provide the Contacts when I actually need them. It's parameterised by another Callable
, so that inner one is also not invoked until you decide you actually need it.
The actual implementations:
public with sharing class LazyContacts implements Callable {
private Callable lazyAccounts;
public LazyContacts(Callable lazyAccounts) {
this.lazyAccounts = lazyAccounts;
}
public Object call(String param1, Map<String, Object> param2) {
return [
SELECT LastName
FROM Contact
WHERE AccountId IN :(List<SObject>)lazyAccounts.call(null, null)
];
}
}
public with sharing class LazyAccounts implements Callable {
private String accountName;
public LazyAccounts(String accountName) {
this.accountName = accountName;
}
public Object call(String param1, Map<String, Object> param2) {
return [
SELECT Id
FROM Account
WHERE Name = :accountName
];
}
}
You could certainly put together something like that in Apex. And you can do similar with iterators - only iterating when the data is actually requested.
The only downside is that Apex is missing a few language niceties that exist in Java and would make the code more succinct (and type-safe if we had templates).
1
Thanks for the response. Interesting approach. I'm not really sure what "Callable" brings to this conversation since, a you point out, we could roll our own interface and do so in a way that doesn't have unused parameters and could have greater type safety... Also doesn't solve the problem of a, a.b, etc possibly being null (but I guess that probably isn't solvable in Apex)
– Brian Kessler
5 hours ago
3
The advantage of callable is that it exists already, so no extra dependencies if you're using unlocked packaging. And it does keep everything very loosely coupled. It seems like you're asking two questions, really: 1. How can I defer evaluation? A: Use callable or something similar 2. How can I avoid lots of null-checks. 1 seems like the bigger problem to me, so that's what I answered. 2 can be done by replacing null with an appropriate actual object e.g. an empty list, or string, or a Null Object. Then make sure you don't do expensive things if the incoming data doesn't need them
– Aidan
5 hours ago
add a comment |
Your Answer
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "459"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsalesforce.stackexchange.com%2fquestions%2f251558%2fis-there-any-way-to-make-an-apex-method-parameter-lazy%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
Not exactly, but you can do something like lazy evaluation by making use of the Callable
interface (or rolling your own). Here's an example using Callable
...
To start with, a test:
@IsTest private class LazyTest {
@TestSetup static void setup() {
List<Account> accounts = new List<Account> {
new Account(Name = 'A'),
new Account(Name = 'B')};
insert accounts;
List<Contact> contacts = new List<Contact> {
new Contact(LastName = '1', AccountId = accounts[0].Id),
new Contact(LastName = '2', AccountId = accounts[1].Id)};
insert contacts;
}
@IsTest static void testBehavior() {
Callable lazyContacts = new LazyContacts(new LazyAccounts('A'));
// No calls made yet, so I can pass this around at no great cost
System.assertEquals(0, Limits.getQueries());
// OK, I've decided I need those contacts now...
List<Contact> results = (List<Contact>)lazyContacts.call(null, null);
System.assertEquals(2, Limits.getQueries());
System.assertEquals(1, results.size());
System.assertEquals('1', results[0].LastName);
}
}
In the test, lazyContacts
is not yet the Contacts I'm looking for. It's like a Callable
that will provide the Contacts when I actually need them. It's parameterised by another Callable
, so that inner one is also not invoked until you decide you actually need it.
The actual implementations:
public with sharing class LazyContacts implements Callable {
private Callable lazyAccounts;
public LazyContacts(Callable lazyAccounts) {
this.lazyAccounts = lazyAccounts;
}
public Object call(String param1, Map<String, Object> param2) {
return [
SELECT LastName
FROM Contact
WHERE AccountId IN :(List<SObject>)lazyAccounts.call(null, null)
];
}
}
public with sharing class LazyAccounts implements Callable {
private String accountName;
public LazyAccounts(String accountName) {
this.accountName = accountName;
}
public Object call(String param1, Map<String, Object> param2) {
return [
SELECT Id
FROM Account
WHERE Name = :accountName
];
}
}
You could certainly put together something like that in Apex. And you can do similar with iterators - only iterating when the data is actually requested.
The only downside is that Apex is missing a few language niceties that exist in Java and would make the code more succinct (and type-safe if we had templates).
1
Thanks for the response. Interesting approach. I'm not really sure what "Callable" brings to this conversation since, a you point out, we could roll our own interface and do so in a way that doesn't have unused parameters and could have greater type safety... Also doesn't solve the problem of a, a.b, etc possibly being null (but I guess that probably isn't solvable in Apex)
– Brian Kessler
5 hours ago
3
The advantage of callable is that it exists already, so no extra dependencies if you're using unlocked packaging. And it does keep everything very loosely coupled. It seems like you're asking two questions, really: 1. How can I defer evaluation? A: Use callable or something similar 2. How can I avoid lots of null-checks. 1 seems like the bigger problem to me, so that's what I answered. 2 can be done by replacing null with an appropriate actual object e.g. an empty list, or string, or a Null Object. Then make sure you don't do expensive things if the incoming data doesn't need them
– Aidan
5 hours ago
add a comment |
Not exactly, but you can do something like lazy evaluation by making use of the Callable
interface (or rolling your own). Here's an example using Callable
...
To start with, a test:
@IsTest private class LazyTest {
@TestSetup static void setup() {
List<Account> accounts = new List<Account> {
new Account(Name = 'A'),
new Account(Name = 'B')};
insert accounts;
List<Contact> contacts = new List<Contact> {
new Contact(LastName = '1', AccountId = accounts[0].Id),
new Contact(LastName = '2', AccountId = accounts[1].Id)};
insert contacts;
}
@IsTest static void testBehavior() {
Callable lazyContacts = new LazyContacts(new LazyAccounts('A'));
// No calls made yet, so I can pass this around at no great cost
System.assertEquals(0, Limits.getQueries());
// OK, I've decided I need those contacts now...
List<Contact> results = (List<Contact>)lazyContacts.call(null, null);
System.assertEquals(2, Limits.getQueries());
System.assertEquals(1, results.size());
System.assertEquals('1', results[0].LastName);
}
}
In the test, lazyContacts
is not yet the Contacts I'm looking for. It's like a Callable
that will provide the Contacts when I actually need them. It's parameterised by another Callable
, so that inner one is also not invoked until you decide you actually need it.
The actual implementations:
public with sharing class LazyContacts implements Callable {
private Callable lazyAccounts;
public LazyContacts(Callable lazyAccounts) {
this.lazyAccounts = lazyAccounts;
}
public Object call(String param1, Map<String, Object> param2) {
return [
SELECT LastName
FROM Contact
WHERE AccountId IN :(List<SObject>)lazyAccounts.call(null, null)
];
}
}
public with sharing class LazyAccounts implements Callable {
private String accountName;
public LazyAccounts(String accountName) {
this.accountName = accountName;
}
public Object call(String param1, Map<String, Object> param2) {
return [
SELECT Id
FROM Account
WHERE Name = :accountName
];
}
}
You could certainly put together something like that in Apex. And you can do similar with iterators - only iterating when the data is actually requested.
The only downside is that Apex is missing a few language niceties that exist in Java and would make the code more succinct (and type-safe if we had templates).
1
Thanks for the response. Interesting approach. I'm not really sure what "Callable" brings to this conversation since, a you point out, we could roll our own interface and do so in a way that doesn't have unused parameters and could have greater type safety... Also doesn't solve the problem of a, a.b, etc possibly being null (but I guess that probably isn't solvable in Apex)
– Brian Kessler
5 hours ago
3
The advantage of callable is that it exists already, so no extra dependencies if you're using unlocked packaging. And it does keep everything very loosely coupled. It seems like you're asking two questions, really: 1. How can I defer evaluation? A: Use callable or something similar 2. How can I avoid lots of null-checks. 1 seems like the bigger problem to me, so that's what I answered. 2 can be done by replacing null with an appropriate actual object e.g. an empty list, or string, or a Null Object. Then make sure you don't do expensive things if the incoming data doesn't need them
– Aidan
5 hours ago
add a comment |
Not exactly, but you can do something like lazy evaluation by making use of the Callable
interface (or rolling your own). Here's an example using Callable
...
To start with, a test:
@IsTest private class LazyTest {
@TestSetup static void setup() {
List<Account> accounts = new List<Account> {
new Account(Name = 'A'),
new Account(Name = 'B')};
insert accounts;
List<Contact> contacts = new List<Contact> {
new Contact(LastName = '1', AccountId = accounts[0].Id),
new Contact(LastName = '2', AccountId = accounts[1].Id)};
insert contacts;
}
@IsTest static void testBehavior() {
Callable lazyContacts = new LazyContacts(new LazyAccounts('A'));
// No calls made yet, so I can pass this around at no great cost
System.assertEquals(0, Limits.getQueries());
// OK, I've decided I need those contacts now...
List<Contact> results = (List<Contact>)lazyContacts.call(null, null);
System.assertEquals(2, Limits.getQueries());
System.assertEquals(1, results.size());
System.assertEquals('1', results[0].LastName);
}
}
In the test, lazyContacts
is not yet the Contacts I'm looking for. It's like a Callable
that will provide the Contacts when I actually need them. It's parameterised by another Callable
, so that inner one is also not invoked until you decide you actually need it.
The actual implementations:
public with sharing class LazyContacts implements Callable {
private Callable lazyAccounts;
public LazyContacts(Callable lazyAccounts) {
this.lazyAccounts = lazyAccounts;
}
public Object call(String param1, Map<String, Object> param2) {
return [
SELECT LastName
FROM Contact
WHERE AccountId IN :(List<SObject>)lazyAccounts.call(null, null)
];
}
}
public with sharing class LazyAccounts implements Callable {
private String accountName;
public LazyAccounts(String accountName) {
this.accountName = accountName;
}
public Object call(String param1, Map<String, Object> param2) {
return [
SELECT Id
FROM Account
WHERE Name = :accountName
];
}
}
You could certainly put together something like that in Apex. And you can do similar with iterators - only iterating when the data is actually requested.
The only downside is that Apex is missing a few language niceties that exist in Java and would make the code more succinct (and type-safe if we had templates).
Not exactly, but you can do something like lazy evaluation by making use of the Callable
interface (or rolling your own). Here's an example using Callable
...
To start with, a test:
@IsTest private class LazyTest {
@TestSetup static void setup() {
List<Account> accounts = new List<Account> {
new Account(Name = 'A'),
new Account(Name = 'B')};
insert accounts;
List<Contact> contacts = new List<Contact> {
new Contact(LastName = '1', AccountId = accounts[0].Id),
new Contact(LastName = '2', AccountId = accounts[1].Id)};
insert contacts;
}
@IsTest static void testBehavior() {
Callable lazyContacts = new LazyContacts(new LazyAccounts('A'));
// No calls made yet, so I can pass this around at no great cost
System.assertEquals(0, Limits.getQueries());
// OK, I've decided I need those contacts now...
List<Contact> results = (List<Contact>)lazyContacts.call(null, null);
System.assertEquals(2, Limits.getQueries());
System.assertEquals(1, results.size());
System.assertEquals('1', results[0].LastName);
}
}
In the test, lazyContacts
is not yet the Contacts I'm looking for. It's like a Callable
that will provide the Contacts when I actually need them. It's parameterised by another Callable
, so that inner one is also not invoked until you decide you actually need it.
The actual implementations:
public with sharing class LazyContacts implements Callable {
private Callable lazyAccounts;
public LazyContacts(Callable lazyAccounts) {
this.lazyAccounts = lazyAccounts;
}
public Object call(String param1, Map<String, Object> param2) {
return [
SELECT LastName
FROM Contact
WHERE AccountId IN :(List<SObject>)lazyAccounts.call(null, null)
];
}
}
public with sharing class LazyAccounts implements Callable {
private String accountName;
public LazyAccounts(String accountName) {
this.accountName = accountName;
}
public Object call(String param1, Map<String, Object> param2) {
return [
SELECT Id
FROM Account
WHERE Name = :accountName
];
}
}
You could certainly put together something like that in Apex. And you can do similar with iterators - only iterating when the data is actually requested.
The only downside is that Apex is missing a few language niceties that exist in Java and would make the code more succinct (and type-safe if we had templates).
answered 6 hours ago
AidanAidan
7,2101144
7,2101144
1
Thanks for the response. Interesting approach. I'm not really sure what "Callable" brings to this conversation since, a you point out, we could roll our own interface and do so in a way that doesn't have unused parameters and could have greater type safety... Also doesn't solve the problem of a, a.b, etc possibly being null (but I guess that probably isn't solvable in Apex)
– Brian Kessler
5 hours ago
3
The advantage of callable is that it exists already, so no extra dependencies if you're using unlocked packaging. And it does keep everything very loosely coupled. It seems like you're asking two questions, really: 1. How can I defer evaluation? A: Use callable or something similar 2. How can I avoid lots of null-checks. 1 seems like the bigger problem to me, so that's what I answered. 2 can be done by replacing null with an appropriate actual object e.g. an empty list, or string, or a Null Object. Then make sure you don't do expensive things if the incoming data doesn't need them
– Aidan
5 hours ago
add a comment |
1
Thanks for the response. Interesting approach. I'm not really sure what "Callable" brings to this conversation since, a you point out, we could roll our own interface and do so in a way that doesn't have unused parameters and could have greater type safety... Also doesn't solve the problem of a, a.b, etc possibly being null (but I guess that probably isn't solvable in Apex)
– Brian Kessler
5 hours ago
3
The advantage of callable is that it exists already, so no extra dependencies if you're using unlocked packaging. And it does keep everything very loosely coupled. It seems like you're asking two questions, really: 1. How can I defer evaluation? A: Use callable or something similar 2. How can I avoid lots of null-checks. 1 seems like the bigger problem to me, so that's what I answered. 2 can be done by replacing null with an appropriate actual object e.g. an empty list, or string, or a Null Object. Then make sure you don't do expensive things if the incoming data doesn't need them
– Aidan
5 hours ago
1
1
Thanks for the response. Interesting approach. I'm not really sure what "Callable" brings to this conversation since, a you point out, we could roll our own interface and do so in a way that doesn't have unused parameters and could have greater type safety... Also doesn't solve the problem of a, a.b, etc possibly being null (but I guess that probably isn't solvable in Apex)
– Brian Kessler
5 hours ago
Thanks for the response. Interesting approach. I'm not really sure what "Callable" brings to this conversation since, a you point out, we could roll our own interface and do so in a way that doesn't have unused parameters and could have greater type safety... Also doesn't solve the problem of a, a.b, etc possibly being null (but I guess that probably isn't solvable in Apex)
– Brian Kessler
5 hours ago
3
3
The advantage of callable is that it exists already, so no extra dependencies if you're using unlocked packaging. And it does keep everything very loosely coupled. It seems like you're asking two questions, really: 1. How can I defer evaluation? A: Use callable or something similar 2. How can I avoid lots of null-checks. 1 seems like the bigger problem to me, so that's what I answered. 2 can be done by replacing null with an appropriate actual object e.g. an empty list, or string, or a Null Object. Then make sure you don't do expensive things if the incoming data doesn't need them
– Aidan
5 hours ago
The advantage of callable is that it exists already, so no extra dependencies if you're using unlocked packaging. And it does keep everything very loosely coupled. It seems like you're asking two questions, really: 1. How can I defer evaluation? A: Use callable or something similar 2. How can I avoid lots of null-checks. 1 seems like the bigger problem to me, so that's what I answered. 2 can be done by replacing null with an appropriate actual object e.g. an empty list, or string, or a Null Object. Then make sure you don't do expensive things if the incoming data doesn't need them
– Aidan
5 hours ago
add a comment |
Thanks for contributing an answer to Salesforce Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsalesforce.stackexchange.com%2fquestions%2f251558%2fis-there-any-way-to-make-an-apex-method-parameter-lazy%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
This Idea would help, though not as nice as having a shortcut like
?
null checks available in .Net.– sfdcfox
5 hours ago